From 714256a744e3555a243a539ddab627b5c5432d82 Mon Sep 17 00:00:00 2001
From: julian laplace
- * 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 connect.
- *
- * @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).
- *
- *
- *
- *
- * @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.
- *
- *
- * @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 connect.
- *
- * @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 connect.
- *
- * @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.
- *
- *
- * @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:
- *
- *
- * 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 input[0]
- * and input[1]. 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 input[1] from the signal connected
- * to input[0]. If an argument is provided in the constructor, the
- * signals .value 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.
- * 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 input[0].
- * @type {Tone.Gain}
- */
- this.a = this.input[0] = new Tone.Gain();
- /**
- * Alias for input[1].
- * @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% input[0] and
- * a value of 1 will output 100% input[1].
- * @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 output[0]
- * @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 output[1]
- * @type {Tone.Filter}
- */
- this.mid = this.output[1] = new Tone.Filter(0, 'lowpass');
- /**
- * The high band output. Alias for output[2]
- * @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 min and
- * max 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: setStateAtTime("state", time)
- * and getValueAtTime(time).
- *
- * @extends {Tone.Timeline}
- * @param {String} initial The initial state of the TimelineState.
- * Defaults to undefined
- */
- 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.
- * A single transport is created for you when the library is initialized.
- *
- * 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.
- *
- * 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.
- *
- * 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 input[0]
- * @type {GainNode}
- */
- this.left = this.input[0] = new Tone.Gain();
- /**
- * The right input channel.
- * Alias for input[1].
- * @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 output[0]
- * @type {Tone.Gain}
- */
- this.left = this.output[0] = new Tone.Gain();
- /**
- * Right channel output.
- * Alias for output[1]
- * @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).
- *
- * Mid = (Left+Right)/sqrt(2); // obtain mid-signal from left and right
- *
- * @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
- *
- * Side = (Left-Right)/sqrt(2); // obtain side-signal from left and righ
- * output[0]
- * @type {Tone.Expr}
- */
- this.mid = this.output[0] = new Tone.Expr('($0 + $1) * $2');
- /**
- * The side output. Connect to side processing. Alias for
- * output[1]
- * @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.
- *
- * Left = (Mid+Side)/sqrt(2); // obtain left signal from mid and side
- *
- * @extends {Tone.StereoEffect}
- * @constructor
- */
- Tone.MidSideMerge = function () {
- this.createInsOuts(2, 0);
- /**
- * The mid signal input. Alias for
- *
- * Right = (Mid-Side)/sqrt(2); // obtain right signal from mid and side
- * input[0]
- * @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
- * input[1]
- * @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.
- *
- *
- * @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.
- *
- * 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.
- *
- * 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:
- * order 2: 2x^2 + 1
- * order 3: 4x^3 + 3x
- * @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).
- *
- * 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).
- *
- *
- * Mid *= 2*(1-width)
- *
- * @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.
- *
- * Side *= 2*width
- *
- *
- * @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).
- *
- *
- * @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.
- *
- *
- * @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.
- *
- *
- * @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).
- *
- *
- * @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
note * .octaves and ramps to
- * note over the duration of .pitchDecay.
- *
- * @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.
- *
- *
- * @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;
-}));
-
-/***/ }),
-/* 2 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.requestAudioContext = exports.intervalInRange = exports.roundInterval = exports.clamp = exports.lerp = exports.browser = exports.mod = exports.choice = undefined;
-
-var _tone = __webpack_require__(1);
-
-var _tone2 = _interopRequireDefault(_tone);
-
-var _startAudioContext = __webpack_require__(14);
-
-var _startAudioContext2 = _interopRequireDefault(_startAudioContext);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-/**
- * Utilities
- * @module lib/util.js;
- */
-
-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 choice(a) {
- return a[Math.floor(Math.random() * a.length)];
-}
-function mod(n, m) {
- return n - m * Math.floor(n / m);
-}
-function roundInterval(interval) {
- return Math.round(interval * 10000000);
-}
-var intervalInRange = function intervalInRange(interval, root) {
- return 20 < interval * root && interval * root < 15000;
-};
-var lerp = function lerp(n, a, b) {
- return (b - a) * n + a;
-};
-var clamp = function clamp(n) {
- var a = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
- var b = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
- return n < a ? a : n < b ? n : b;
-};
-
-function requestAudioContext(fn) {
- if (window.location.protocol !== "https:") {
- 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.browser = browser;
-exports.lerp = lerp;
-exports.clamp = clamp;
-exports.roundInterval = roundInterval;
-exports.intervalInRange = intervalInRange;
-exports.requestAudioContext = requestAudioContext;
-
-/***/ }),
-/* 3 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-/**
-* FUNCTION: isArray( value )
-* Validates if a value is an array.
-*
-* @param {*} value - value to be validated
-* @returns {Boolean} boolean indicating whether value is an array
-*/
-function isArray( value ) {
- return Object.prototype.toString.call( value ) === '[object Array]';
-} // end FUNCTION isArray()
-
-// EXPORTS //
-
-module.exports = Array.isArray || isArray;
-
-
-/***/ }),
-/* 4 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-/**
- * Iquizeles color generator
- * @module lib/color.js;
- */
-
-var palettes = [[[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.0, 0.33, 0.67]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.0, 0.1, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.3, 0.2, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 0.5], [0.8, 0.9, 0.3]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 0.7, 0.4], [0.0, 0.15, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [2.0, 1.0, 0.0], [0.5, 0.2, 0.25]], [[0.8, 0.5, 0.4], [0.2, 0.4, 0.2], [2.0, 1.0, 1.0], [0.0, 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;
-
-/***/ }),
-/* 5 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-
-var _tone = __webpack_require__(1);
-
-var _tone2 = _interopRequireDefault(_tone);
-
-var _util = __webpack_require__(2);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-/**
- * Kalimba
- * @module lib/kalimba.js;
- */
-
-var player_count = 4;
-
-var samples = [{ root: 219.5, fn: "samples/380737__cabled-mess__sansula-01-a-raw.wav" }, { root: 260.9, fn: "samples/380736__cabled-mess__sansula-02-c-raw.wav" }, { root: 330.2, fn: "samples/380735__cabled-mess__sansula-03-e-raw.wav" }];
+ List.prototype.toString = function toString () {
+ return this.__toString('List [', ']');
+ };
-function load(_ref) {
- var output = _ref.output;
+ // @pragma Access
- samples.forEach(function (sample) {
- sample.players = [];
- sample.index = -1;
- for (var i = 0; i < player_count; i++) {
- var fn = sample.fn;
- if (window.location.href.match(/asdf.us/)) {
- fn = "//asdf.us/kalimba/" + fn.replace("wav", "mp3");
- }
- var player = new _tone2.default.Player({
- url: fn,
- retrigger: true,
- playbackRate: 1
- });
- player.name = fn;
- var gain = new _tone2.default.Gain(1.6);
- player.connect(gain);
- gain.connect(output);
- sample.players.push(player);
+ List.prototype.get = function get (index, notSetValue) {
+ index = wrapIndex(this, index);
+ if (index >= 0 && index < this.size) {
+ index += this._origin;
+ var node = listNodeFor(this, index);
+ return node && node.array[index & MASK];
}
- });
- console.log("+ Voices:", samples.reduce(function (count, sample) {
- return count + sample.players.length;
- }, 0));
-}
-
-function play(interval, root) {
- var sample = (0, _util.choice)(samples);
- sample.index = (sample.index + 1) % sample.players.length;
-
- var player = sample.players[sample.index];
- player.playbackRate = interval * root / sample.root;
- player.start();
-}
-
-function pause() {
- // no-op
-}
-
-exports.default = { load: load, play: play, pause: pause };
-
-// for help tuning the kalimba samples
-// function keydown(e) {
-// // console.log(e.keyCode)
-// if (e.metaKey && last) {
-// let step = e.shiftKey ? (e.ctrlKey ? 0.01 : 0.1) : 1;
-// switch (e.keyCode) {
-// case 38: // up
-// e.preventDefault();
-// samples[0].root -= step;
-// play(last);
-// break;
-// case 40: // down
-// e.preventDefault();
-// samples[0].root += step;
-// play(last);
-// break;
-// }
-// console.log(samples[0].root);
-// }
-// }
-// window.addEventListener("keydown", keydown, true);
-
-/***/ }),
-/* 6 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-/**
- * Keyboard helper
- * @module lib/keys.js;
- */
-
-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;
- callback(index);
-}
-
-function listen(fn) {
- callback = fn;
-}
-
-exports.default = { listen: listen };
-
-/***/ }),
-/* 7 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
+ return notSetValue;
+ };
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
+ // @pragma Modification
-var _webmidi = __webpack_require__(30);
+ List.prototype.set = function set (index, value) {
+ return updateList(this, index, value);
+ };
-function enable(play) {
- _webmidi.WebMidi.enable().then(onEnabled).catch(function (error) {
- return console.error(error);
- });
+ List.prototype.remove = function remove (index) {
+ return !this.has(index)
+ ? this
+ : index === 0
+ ? this.shift()
+ : index === this.size - 1
+ ? this.pop()
+ : this.splice(index, 1);
+ };
- // Function triggered when WEBMIDI.js is ready
- function onEnabled() {
- // Display available MIDI input devices
- if (_webmidi.WebMidi.inputs.length < 1) {
- console.log("No device detected.");
- return;
- } else {
- _webmidi.WebMidi.inputs.forEach(function (device, index) {
- document.body.innerHTML += index + ": " + device.name + "
";
- });
- var mySynth = _webmidi.WebMidi.inputs[0];
- // const mySynth = WebMidi.getInputByName("TYPE NAME HERE!")
+ List.prototype.insert = function insert (index, value) {
+ return this.splice(index, 0, value);
+ };
- mySynth.channels[1].addListener("noteon", function (event) {
- console.log(event.note);
- });
+ List.prototype.clear = function clear () {
+ if (this.size === 0) {
+ return this;
}
- }
-} /**
- * MIDI
- * @module midi.js;
- */
-
-exports.default = { enable: enable };
-
-/***/ }),
-/* 8 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-
-var _tone = __webpack_require__(1);
-
-var _tone2 = _interopRequireDefault(_tone);
-
-var _util = __webpack_require__(2);
-
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
-/**
- * Sine wave organ
- * @module lib/organ.js;
- */
-
-var root = 440;
+ if (this.__ownerID) {
+ this.size = this._origin = this._capacity = 0;
+ this._level = SHIFT;
+ this._root = this._tail = this.__hash = undefined;
+ this.__altered = true;
+ return this;
+ }
+ return emptyList();
+ };
-var oscillators = {};
-var output = void 0;
-var lastPlayed = void 0;
+ List.prototype.push = function push (/*...values*/) {
+ var values = arguments;
+ var oldSize = this.size;
+ return this.withMutations(function (list) {
+ setListBounds(list, 0, oldSize + values.length);
+ for (var ii = 0; ii < values.length; ii++) {
+ list.set(oldSize + ii, values[ii]);
+ }
+ });
+ };
-function load(out) {
- output = out;
-}
-function isPlaying(interval) {
- var rounded = (0, _util.roundInterval)(interval);
- var osc = oscillators[rounded];
- return osc && osc.playing;
-}
-function play(interval) {
- if (!output) {
- return;
- }
- var rounded = (0, _util.roundInterval)(interval);
- var osc = oscillators[rounded] = oscillators[rounded] || {};
- if (!osc.el) {
- osc.interval = interval;
- osc.el = new _tone2.default.Oscillator(interval * root, "sine");
- osc.el.connect(output);
- }
- osc.el.start();
- osc.playing = true;
- lastPlayed = osc;
- return osc;
-}
+ List.prototype.pop = function pop () {
+ return setListBounds(this, 0, -1);
+ };
-function pause(interval) {
- var rounded = (0, _util.roundInterval)(interval);
- if (!oscillators[rounded]) return;
- var osc = oscillators[rounded] = oscillators[rounded] || {};
- if (osc.el) {
- osc.el.stop();
- }
- osc.playing = false;
- return osc;
-}
+ List.prototype.unshift = function unshift (/*...values*/) {
+ var values = arguments;
+ return this.withMutations(function (list) {
+ setListBounds(list, -values.length);
+ for (var ii = 0; ii < values.length; ii++) {
+ list.set(ii, values[ii]);
+ }
+ });
+ };
-function setRoot(newRoot) {
- root = newRoot;
- var _iteratorNormalCompletion = true;
- var _didIteratorError = false;
- var _iteratorError = undefined;
+ List.prototype.shift = function shift () {
+ return setListBounds(this, 1);
+ };
- try {
- for (var _iterator = Object.values(oscillators)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
- var osc = _step.value;
+ List.prototype.shuffle = function shuffle (random) {
+ if ( random === void 0 ) random = Math.random;
- osc.el.frequency.value = osc.interval * newRoot;
- }
- } catch (err) {
- _didIteratorError = true;
- _iteratorError = err;
- } finally {
- try {
- if (!_iteratorNormalCompletion && _iterator.return) {
- _iterator.return();
- }
- } finally {
- if (_didIteratorError) {
- throw _iteratorError;
- }
- }
- }
-}
-function stop() {
- var _iteratorNormalCompletion2 = true;
- var _didIteratorError2 = false;
- var _iteratorError2 = undefined;
+ return this.withMutations(function (mutable) {
+ // implementation of the Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
+ var current = mutable.size;
+ var destination;
+ var tmp;
- try {
- for (var _iterator2 = Object.values(oscillators)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
- var osc = _step2.value;
+ while (current) {
+ destination = Math.floor(random() * current--);
- osc.el.stop();
- osc.el.disconnect();
- osc.playing = false;
- delete osc.el;
- }
- } catch (err) {
- _didIteratorError2 = true;
- _iteratorError2 = err;
- } finally {
- try {
- if (!_iteratorNormalCompletion2 && _iterator2.return) {
- _iterator2.return();
+ tmp = mutable.get(destination);
+ mutable.set(destination, mutable.get(current));
+ mutable.set(current, tmp);
}
- } finally {
- if (_didIteratorError2) {
- throw _iteratorError2;
+ });
+ };
+
+ // @pragma Composition
+
+ List.prototype.concat = function concat (/*...collections*/) {
+ var arguments$1 = arguments;
+
+ var seqs = [];
+ for (var i = 0; i < arguments.length; i++) {
+ var argument = arguments$1[i];
+ var seq = IndexedCollection(
+ typeof argument !== 'string' && hasIterator(argument)
+ ? argument
+ : [argument]
+ );
+ if (seq.size !== 0) {
+ seqs.push(seq);
}
}
- }
-
- oscillators = {};
-}
+ if (seqs.length === 0) {
+ return this;
+ }
+ if (this.size === 0 && !this.__ownerID && seqs.length === 1) {
+ return this.constructor(seqs[0]);
+ }
+ return this.withMutations(function (list) {
+ seqs.forEach(function (seq) { return seq.forEach(function (value) { return list.push(value); }); });
+ });
+ };
-exports.default = { load: load, isPlaying: isPlaying, play: play, pause: pause, stop: stop, setRoot: setRoot };
+ List.prototype.setSize = function setSize (size) {
+ return setListBounds(this, 0, size);
+ };
-/***/ }),
-/* 9 */
-/***/ (function(module, exports, __webpack_require__) {
+ List.prototype.map = function map (mapper, context) {
+ var this$1$1 = this;
-"use strict";
+ return this.withMutations(function (list) {
+ for (var i = 0; i < this$1$1.size; i++) {
+ list.set(i, mapper.call(context, list.get(i), i, this$1$1));
+ }
+ });
+ };
+ // @pragma Iteration
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.getOutput = getOutput;
+ List.prototype.slice = function slice (begin, end) {
+ var size = this.size;
+ if (wholeSlice(begin, end, size)) {
+ return this;
+ }
+ return setListBounds(
+ this,
+ resolveBegin(begin, size),
+ resolveEnd(end, size)
+ );
+ };
-var _tone = __webpack_require__(1);
+ List.prototype.__iterator = function __iterator (type, reverse) {
+ var index = reverse ? this.size : 0;
+ var values = iterateList(this, reverse);
+ return new Iterator(function () {
+ var value = values();
+ return value === DONE
+ ? iteratorDone()
+ : iteratorValue(type, reverse ? --index : index++, value);
+ });
+ };
-var _tone2 = _interopRequireDefault(_tone);
+ List.prototype.__iterate = function __iterate (fn, reverse) {
+ var index = reverse ? this.size : 0;
+ var values = iterateList(this, reverse);
+ var value;
+ while ((value = values()) !== DONE) {
+ if (fn(value, reverse ? --index : index++, this) === false) {
+ break;
+ }
+ }
+ return index;
+ };
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+ List.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+ if (ownerID === this.__ownerID) {
+ return this;
+ }
+ if (!ownerID) {
+ if (this.size === 0) {
+ return emptyList();
+ }
+ this.__ownerID = ownerID;
+ this.__altered = false;
+ return this;
+ }
+ return makeList(
+ this._origin,
+ this._capacity,
+ this._level,
+ this._root,
+ this._tail,
+ ownerID,
+ this.__hash
+ );
+ };
-var output = null; /**
- * Common output stage
- * @module lib/output.js;
- */
+ return List;
+}(IndexedCollection));
-function getOutput() {
- if (!output) output = makeOutput();
- return output;
-}
+List.isList = isList;
-function makeOutput() {
- var compressor = new _tone2.default.Compressor(-30, 3);
- var gain = new _tone2.default.Gain(0.3);
- compressor.connect(gain);
- gain.toMaster();
+var ListPrototype = List.prototype;
+ListPrototype[IS_LIST_SYMBOL] = true;
+ListPrototype[DELETE] = ListPrototype.remove;
+ListPrototype.merge = ListPrototype.concat;
+ListPrototype.setIn = setIn;
+ListPrototype.deleteIn = ListPrototype.removeIn = deleteIn;
+ListPrototype.update = update;
+ListPrototype.updateIn = updateIn;
+ListPrototype.mergeIn = mergeIn;
+ListPrototype.mergeDeepIn = mergeDeepIn;
+ListPrototype.withMutations = withMutations;
+ListPrototype.wasAltered = wasAltered;
+ListPrototype.asImmutable = asImmutable;
+ListPrototype['@@transducer/init'] = ListPrototype.asMutable = asMutable;
+ListPrototype['@@transducer/step'] = function (result, arr) {
+ return result.push(arr);
+};
+ListPrototype['@@transducer/result'] = function (obj) {
+ return obj.asImmutable();
+};
- return compressor;
-}
+var VNode = function VNode(array, ownerID) {
+ this.array = array;
+ this.ownerID = ownerID;
+};
-/***/ }),
-/* 10 */
-/***/ (function(module, exports, __webpack_require__) {
+// TODO: seems like these methods are very similar
-"use strict";
+VNode.prototype.removeBefore = function removeBefore (ownerID, level, index) {
+ if (
+ (index & ((1 << (level + SHIFT)) - 1)) === 0 ||
+ this.array.length === 0
+ ) {
+ return this;
+ }
+ var originIndex = (index >>> level) & MASK;
+ if (originIndex >= this.array.length) {
+ return new VNode([], ownerID);
+ }
+ var removingFirst = originIndex === 0;
+ var newChild;
+ if (level > 0) {
+ var oldChild = this.array[originIndex];
+ newChild =
+ oldChild && oldChild.removeBefore(ownerID, level - SHIFT, index);
+ if (newChild === oldChild && removingFirst) {
+ return this;
+ }
+ }
+ if (removingFirst && !newChild) {
+ return this;
+ }
+ var editable = editableVNode(this, ownerID);
+ if (!removingFirst) {
+ for (var ii = 0; ii < originIndex; ii++) {
+ editable.array[ii] = undefined;
+ }
+ }
+ if (newChild) {
+ editable.array[originIndex] = newChild;
+ }
+ return editable;
+};
+VNode.prototype.removeAfter = function removeAfter (ownerID, level, index) {
+ if (
+ index === (level ? 1 << (level + SHIFT) : SIZE) ||
+ this.array.length === 0
+ ) {
+ return this;
+ }
+ var sizeIndex = ((index - 1) >>> level) & MASK;
+ if (sizeIndex >= this.array.length) {
+ return this;
+ }
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.load = load;
-exports.dragOver = dragOver;
-exports.drop = drop;
-exports.loadSampleFromFile = loadSampleFromFile;
+ var newChild;
+ if (level > 0) {
+ var oldChild = this.array[sizeIndex];
+ newChild =
+ oldChild && oldChild.removeAfter(ownerID, level - SHIFT, index);
+ if (newChild === oldChild && sizeIndex === this.array.length - 1) {
+ return this;
+ }
+ }
-var _tone = __webpack_require__(1);
+ var editable = editableVNode(this, ownerID);
+ editable.array.splice(sizeIndex + 1);
+ if (newChild) {
+ editable.array[sizeIndex] = newChild;
+ }
+ return editable;
+};
-var _tone2 = _interopRequireDefault(_tone);
+var DONE = {};
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+function iterateList(list, reverse) {
+ var left = list._origin;
+ var right = list._capacity;
+ var tailPos = getTailOffset(right);
+ var tail = list._tail;
-function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /**
- * Sampler
- * @module lib/sampler.js;
- */
+ return iterateNodeOrLeaf(list._root, list._level, 0);
-var root = 440;
+ function iterateNodeOrLeaf(node, level, offset) {
+ return level === 0
+ ? iterateLeaf(node, offset)
+ : iterateNode(node, level, offset);
+ }
-var output = void 0;
-var ready = void 0;
-var current = "";
-var samples = {};
+ function iterateLeaf(node, offset) {
+ var array = offset === tailPos ? tail && tail.array : node && node.array;
+ var from = offset > left ? 0 : left - offset;
+ var to = right - offset;
+ if (to > SIZE) {
+ to = SIZE;
+ }
+ return function () {
+ if (from === to) {
+ return DONE;
+ }
+ var idx = reverse ? --to : from++;
+ return array && array[idx];
+ };
+ }
-var player_count = 12;
+ function iterateNode(node, level, offset) {
+ var values;
+ var array = node && node.array;
+ var from = offset > left ? 0 : (left - offset) >> level;
+ var to = ((right - offset) >> level) + 1;
+ if (to > SIZE) {
+ to = SIZE;
+ }
+ return function () {
+ while (true) {
+ if (values) {
+ var value = values();
+ if (value !== DONE) {
+ return value;
+ }
+ values = null;
+ }
+ if (from === to) {
+ return DONE;
+ }
+ var idx = reverse ? --to : from++;
+ values = iterateNodeOrLeaf(
+ array && array[idx],
+ level - SHIFT,
+ offset + (idx << level)
+ );
+ }
+ };
+ }
+}
-function load(out, readyCallback) {
- output = out;
- ready = readyCallback;
- document.body.addEventListener("dragover", dragOver);
- document.body.addEventListener("drop", drop);
+function makeList(origin, capacity, level, root, tail, ownerID, hash) {
+ var list = Object.create(ListPrototype);
+ list.size = capacity - origin;
+ list._origin = origin;
+ list._capacity = capacity;
+ list._level = level;
+ list._root = root;
+ list._tail = tail;
+ list.__ownerID = ownerID;
+ list.__hash = hash;
+ list.__altered = false;
+ return list;
}
-/**
- * Drag and drop
- */
-function dragOver(event) {
- event.preventDefault();
+function emptyList() {
+ return makeList(0, 0, SHIFT);
}
-function drop(event) {
- event.preventDefault();
- var files = event.dataTransfer.items ? [].concat(_toConsumableArray(event.dataTransfer.items)).filter(function (item) {
- return item.kind === "file";
- }).map(function (item) {
- return item.getAsFile();
- }) : [].concat(_toConsumableArray(event.dataTransfer.files));
- var file = files[0];
- var reader = new FileReader();
+function updateList(list, index, value) {
+ index = wrapIndex(list, index);
- reader.addEventListener("load", function () {
- return loadSampleFromFile(file, reader.result);
- }, false);
+ if (index !== index) {
+ return list;
+ }
- if (file) {
- reader.readAsDataURL(file);
+ if (index >= list.size || index < 0) {
+ return list.withMutations(function (list) {
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+ index < 0
+ ? setListBounds(list, index).set(0, value)
+ : setListBounds(list, 0, index + 1).set(index, value);
+ });
}
-}
-function loadSampleFromFile(file, url) {
- var name = file.name;
+ index += list._origin;
- current = name;
+ var newTail = list._tail;
+ var newRoot = list._root;
+ var didAlter = MakeRef();
+ if (index >= getTailOffset(list._capacity)) {
+ newTail = updateVNode(newTail, list.__ownerID, 0, index, value, didAlter);
+ } else {
+ newRoot = updateVNode(
+ newRoot,
+ list.__ownerID,
+ list._level,
+ index,
+ value,
+ didAlter
+ );
+ }
- var sample = samples[name] = samples[name] || {};
- sample.root = 440;
- sample.players = [];
- sample.index = -1;
- for (var i = 0; i < player_count; i++) {
- var player = new _tone2.default.Player({
- url: url,
- retrigger: true,
- playbackRate: 1
- });
- player.name = name;
- player.connect(output);
- sample.players.push(player);
+ if (!didAlter.value) {
+ return list;
}
- console.log("+ Sampler:", name, "(" + sample.players.length + " voices)");
- ready();
-}
-/**
- * Player
- */
-var last = [1, 440];
+ if (list.__ownerID) {
+ list._root = newRoot;
+ list._tail = newTail;
+ list.__hash = undefined;
+ list.__altered = true;
+ return list;
+ }
+ return makeList(list._origin, list._capacity, list._level, newRoot, newTail);
+}
-function stop() {
- var _iteratorNormalCompletion = true;
- var _didIteratorError = false;
- var _iteratorError = undefined;
+function updateVNode(node, ownerID, level, index, value, didAlter) {
+ var idx = (index >>> level) & MASK;
+ var nodeHas = node && idx < node.array.length;
+ if (!nodeHas && value === undefined) {
+ return node;
+ }
- try {
- for (var _iterator = Object.values(samples)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
- var sample = _step.value;
+ var newNode;
- sample.players.forEach(function (player) {
- return player.stop();
- });
- }
- } catch (err) {
- _didIteratorError = true;
- _iteratorError = err;
- } finally {
- try {
- if (!_iteratorNormalCompletion && _iterator.return) {
- _iterator.return();
- }
- } finally {
- if (_didIteratorError) {
- throw _iteratorError;
- }
+ if (level > 0) {
+ var lowerNode = node && node.array[idx];
+ var newLowerNode = updateVNode(
+ lowerNode,
+ ownerID,
+ level - SHIFT,
+ index,
+ value,
+ didAlter
+ );
+ if (newLowerNode === lowerNode) {
+ return node;
}
+ newNode = editableVNode(node, ownerID);
+ newNode.array[idx] = newLowerNode;
+ return newNode;
}
-}
-function play(interval, root) {
- last = [interval, root];
- var sample = samples[current];
- sample.index = (sample.index + 1) % sample.players.length;
- var player = sample.players[sample.index];
- player.playbackRate = interval * root / sample.root;
- player.start();
-}
-function pause() {
- // no-op
-}
+ if (nodeHas && node.array[idx] === value) {
+ return node;
+ }
-exports.default = { load: load, play: play, pause: pause, stop: stop };
+ if (didAlter) {
+ SetRef(didAlter);
+ }
-// for help tuning
+ newNode = editableVNode(node, ownerID);
+ if (value === undefined && idx === newNode.array.length - 1) {
+ newNode.array.pop();
+ } else {
+ newNode.array[idx] = value;
+ }
+ return newNode;
+}
-function keydown(e) {
- // console.log(e.keyCode)
- if (e.metaKey && last && current) {
- var sample = samples[current];
- var step = e.shiftKey ? e.ctrlKey ? 0.1 : 1 : 10;
- switch (e.keyCode) {
- case 38:
- // up
- e.preventDefault();
- sample.root -= step;
- stop();
- play(last[0], last[1]);
- break;
- case 40:
- // down
- e.preventDefault();
- sample.root += step;
- stop();
- play(last[0], last[1]);
- break;
- }
+function editableVNode(node, ownerID) {
+ if (ownerID && node && ownerID === node.ownerID) {
+ return node;
}
+ return new VNode(node ? node.array.slice() : [], ownerID);
}
-window.addEventListener("keydown", keydown, true);
-/***/ }),
-/* 11 */
-/***/ (function(module, exports, __webpack_require__) {
+function listNodeFor(list, rawIndex) {
+ if (rawIndex >= getTailOffset(list._capacity)) {
+ return list._tail;
+ }
+ if (rawIndex < 1 << (list._level + SHIFT)) {
+ var node = list._root;
+ var level = list._level;
+ while (node && level > 0) {
+ node = node.array[(rawIndex >>> level) & MASK];
+ level -= SHIFT;
+ }
+ return node;
+ }
+}
-"use strict";
+function setListBounds(list, begin, end) {
+ // Sanitize begin & end using this shorthand for ToInt32(argument)
+ // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32
+ if (begin !== undefined) {
+ begin |= 0;
+ }
+ if (end !== undefined) {
+ end |= 0;
+ }
+ var owner = list.__ownerID || new OwnerID();
+ var oldOrigin = list._origin;
+ var oldCapacity = list._capacity;
+ var newOrigin = oldOrigin + begin;
+ var newCapacity =
+ end === undefined
+ ? oldCapacity
+ : end < 0
+ ? oldCapacity + end
+ : oldOrigin + end;
+ if (newOrigin === oldOrigin && newCapacity === oldCapacity) {
+ return list;
+ }
+ // If it's going to end after it starts, it's empty.
+ if (newOrigin >= newCapacity) {
+ return list.clear();
+ }
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.scales = undefined;
+ var newLevel = list._level;
+ var newRoot = list._root;
-__webpack_require__(635);
+ // New origin might need creating a higher root.
+ var offsetShift = 0;
+ while (newOrigin + offsetShift < 0) {
+ newRoot = new VNode(
+ newRoot && newRoot.array.length ? [undefined, newRoot] : [],
+ owner
+ );
+ newLevel += SHIFT;
+ offsetShift += 1 << newLevel;
+ }
+ if (offsetShift) {
+ newOrigin += offsetShift;
+ oldOrigin += offsetShift;
+ newCapacity += offsetShift;
+ oldCapacity += offsetShift;
+ }
-__webpack_require__(636);
+ var oldTailOffset = getTailOffset(oldCapacity);
+ var newTailOffset = getTailOffset(newCapacity);
-var _index = __webpack_require__(19);
+ // New size might need creating a higher root.
+ while (newTailOffset >= 1 << (newLevel + SHIFT)) {
+ newRoot = new VNode(
+ newRoot && newRoot.array.length ? [newRoot] : [],
+ owner
+ );
+ newLevel += SHIFT;
+ }
-var a = void 0,
- b = void 0; /**
- * Scales
- * @module client/lib/scales.js;
- */
+ // Locate or create the new tail.
+ var oldTail = list._tail;
+ var newTail =
+ newTailOffset < oldTailOffset
+ ? listNodeFor(list, newCapacity - 1)
+ : newTailOffset > oldTailOffset
+ ? new VNode([], owner)
+ : oldTail;
-var scales = exports.scales = [{ name: "natural", get: function get(i, j) {
- return [i + 1, j + 1];
- } }, { name: "undertone", get: function get(i, j) {
- return [i + 1, i + j + 2];
- } }, { name: "overtone", get: function get(i, j) {
- return [i + j + 2, j + 1];
- } }, {
- name: "primes",
- reset: function reset(x, y, w, h) {
- a = (0, _index.Prime)().skip(x).take(w).toJS();
- b = (0, _index.Prime)().skip(y).take(h).toJS();
- },
- get: function get(ii, jj, i, j) {
- return [a[i], b[j]];
- }
-}, {
- name: "arithmetic",
- reset: function reset(x, y, w, h) {
- a = (0, _index.Arithmetic)(x + 1, x + 1).take(w).toJS();
- b = (0, _index.Arithmetic)(y + 1, y + 1).take(h).toJS();
- console.log(a);
- },
- get: function get(ii, jj, i, j) {
- return [a[i], b[j]];
- }
-},
-// {
-// name: "triangle",
-// reset: (x, y, w, h) => {
-// a = Triangle().skip(x).take(w).toJS();
-// b = Triangle().skip(y).take(h).toJS();
-// },
-// get: (ii, jj, i, j) => [a[i], b[j]],
-// },
-{
- name: "collatz",
- reset: function reset(x, y, w, h) {
- a = (0, _index.Collatz)(x + 1).take(w).toJS();
- b = (0, _index.Collatz)(y + 1).take(h).toJS();
- },
- get: function get(ii, jj, i, j) {
- return [a[i], b[j]];
+ // Merge Tail into tree.
+ if (
+ oldTail &&
+ newTailOffset > oldTailOffset &&
+ newOrigin < oldCapacity &&
+ oldTail.array.length
+ ) {
+ newRoot = editableVNode(newRoot, owner);
+ var node = newRoot;
+ for (var level = newLevel; level > SHIFT; level -= SHIFT) {
+ var idx = (oldTailOffset >>> level) & MASK;
+ node = node.array[idx] = editableVNode(node.array[idx], owner);
+ }
+ node.array[(oldTailOffset >>> SHIFT) & MASK] = oldTail;
}
-}, {
- name: "pythagorean",
- get: function get(i, j) {
- return i < j ? [Math.pow(3, i + 1), Math.pow(2, j + Math.ceil(Math.max(0, i * 1.0 / 2)))] : [Math.pow(2, i + Math.ceil(Math.max(0, j * 1.2 / 2))), Math.pow(3, j)];
+
+ // If the size has been reduced, there's a chance the tail needs to be trimmed.
+ if (newCapacity < oldCapacity) {
+ newTail = newTail && newTail.removeAfter(owner, 0, newCapacity);
}
-}];
-/***/ }),
-/* 12 */
-/***/ (function(module, exports, __webpack_require__) {
+ // If the new origin is within the tail, then we do not need a root.
+ if (newOrigin >= newTailOffset) {
+ newOrigin -= newTailOffset;
+ newCapacity -= newTailOffset;
+ newLevel = SHIFT;
+ newRoot = null;
+ newTail = newTail && newTail.removeBefore(owner, 0, newOrigin);
-"use strict";
+ // Otherwise, if the root has been trimmed, garbage collect.
+ } else if (newOrigin > oldOrigin || newTailOffset < oldTailOffset) {
+ offsetShift = 0;
+ // Identify the new top root node of the subtree of the old root.
+ while (newRoot) {
+ var beginIndex = (newOrigin >>> newLevel) & MASK;
+ if ((beginIndex !== newTailOffset >>> newLevel) & MASK) {
+ break;
+ }
+ if (beginIndex) {
+ offsetShift += (1 << newLevel) * beginIndex;
+ }
+ newLevel -= SHIFT;
+ newRoot = newRoot.array[beginIndex];
+ }
-// MODULES //
+ // Trim the new sides of the new root.
+ if (newRoot && newOrigin > oldOrigin) {
+ newRoot = newRoot.removeBefore(owner, newLevel, newOrigin - offsetShift);
+ }
+ if (newRoot && newTailOffset < oldTailOffset) {
+ newRoot = newRoot.removeAfter(
+ owner,
+ newLevel,
+ newTailOffset - offsetShift
+ );
+ }
+ if (offsetShift) {
+ newOrigin -= offsetShift;
+ newCapacity -= offsetShift;
+ }
+ }
-var isArray = __webpack_require__( 3 ),
- isIntegerArray = __webpack_require__( 27 ),
- isFunction = __webpack_require__( 26 );
+ if (list.__ownerID) {
+ list.size = newCapacity - newOrigin;
+ list._origin = newOrigin;
+ list._capacity = newCapacity;
+ list._level = newLevel;
+ list._root = newRoot;
+ list._tail = newTail;
+ list.__hash = undefined;
+ list.__altered = true;
+ return list;
+ }
+ return makeList(newOrigin, newCapacity, newLevel, newRoot, newTail);
+}
+function getTailOffset(size) {
+ return size < SIZE ? 0 : ((size - 1) >>> SHIFT) << SHIFT;
+}
-// VARIABLES //
+var OrderedMap = /*@__PURE__*/(function (Map) {
+ function OrderedMap(value) {
+ // eslint-disable-next-line no-constructor-return
+ return value === undefined || value === null
+ ? emptyOrderedMap()
+ : isOrderedMap(value)
+ ? value
+ : emptyOrderedMap().withMutations(function (map) {
+ var iter = KeyedCollection(value);
+ assertNotInfinite(iter.size);
+ iter.forEach(function (v, k) { return map.set(k, v); });
+ });
+ }
-var MAXINT = Math.pow( 2, 31 ) - 1;
+ if ( Map ) OrderedMap.__proto__ = Map;
+ OrderedMap.prototype = Object.create( Map && Map.prototype );
+ OrderedMap.prototype.constructor = OrderedMap;
+ OrderedMap.of = function of (/*...values*/) {
+ return this(arguments);
+ };
-// FUNCTIONS //
+ OrderedMap.prototype.toString = function toString () {
+ return this.__toString('OrderedMap {', '}');
+ };
-/**
-* FUNCTION: gcd( a, b )
-* Computes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm.
-*
-* @param {Number} a - integer
-* @param {Number} b - integer
-* @returns {Number} greatest common divisor
-*/
-function gcd( a, b ) {
- var k = 1,
- t;
- // Simple cases:
- if ( a === 0 ) {
- return b;
- }
- if ( b === 0 ) {
- return a;
- }
- // Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...
- while ( a%2 === 0 && b%2 === 0 ) {
- a = a / 2; // right shift
- b = b / 2; // right shift
- k = k * 2; // left shift
- }
- // Reduce `a` to an odd number...
- while ( a%2 === 0 ) {
- a = a / 2; // right shift
- }
- // Henceforth, `a` is always odd...
- while ( b ) {
- // Remove all factors of 2 in `b`, as they are not common...
- while ( b%2 === 0 ) {
- b = b / 2; // right shift
- }
- // `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...
- if ( a > b ) {
- t = b;
- b = a;
- a = t;
- }
- b = b - a; // b=0 iff b=a
- }
- // Restore common factors of 2...
- return k * a;
-} // end FUNCTION gcd()
+ // @pragma Access
-/**
-* FUNCTION: bitwise( a, b )
-* Computes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm and bitwise operations.
-*
-* @param {Number} a - safe integer
-* @param {Number} b - safe integer
-* @returns {Number} greatest common divisor
-*/
-function bitwise( a, b ) {
- var k = 0,
- t;
- // Simple cases:
- if ( a === 0 ) {
- return b;
- }
- if ( b === 0 ) {
- return a;
- }
- // Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...
- while ( (a & 1) === 0 && (b & 1) === 0 ) {
- a >>>= 1; // right shift
- b >>>= 1; // right shift
- k++;
- }
- // Reduce `a` to an odd number...
- while ( (a & 1) === 0 ) {
- a >>>= 1; // right shift
- }
- // Henceforth, `a` is always odd...
- while ( b ) {
- // Remove all factors of 2 in `b`, as they are not common...
- while ( (b & 1) === 0 ) {
- b >>>= 1; // right shift
- }
- // `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...
- if ( a > b ) {
- t = b;
- b = a;
- a = t;
- }
- b = b - a; // b=0 iff b=a
- }
- // Restore common factors of 2...
- return a << k;
-} // end FUNCTION bitwise()
+ OrderedMap.prototype.get = function get (k, notSetValue) {
+ var index = this._map.get(k);
+ return index !== undefined ? this._list.get(index)[1] : notSetValue;
+ };
+ // @pragma Modification
-// GREATEST COMMON DIVISOR //
+ OrderedMap.prototype.clear = function clear () {
+ if (this.size === 0) {
+ return this;
+ }
+ if (this.__ownerID) {
+ this.size = 0;
+ this._map.clear();
+ this._list.clear();
+ this.__altered = true;
+ return this;
+ }
+ return emptyOrderedMap();
+ };
-/**
-* FUNCTION: compute( arr[, clbk] )
-* Computes the greatest common divisor.
-*
-* @param {Number[]|Number} arr - input array of integers
-* @param {Function|Number} [clbk] - accessor function for accessing array values
-* @returns {Number|Null} greatest common divisor or null
-*/
-function compute() {
- var nargs = arguments.length,
- args,
- clbk,
- arr,
- len,
- a, b,
- i;
+ OrderedMap.prototype.set = function set (k, v) {
+ return updateOrderedMap(this, k, v);
+ };
- // Copy the input arguments to an array...
- args = new Array( nargs );
- for ( i = 0; i < nargs; i++ ) {
- args[ i ] = arguments[ i ];
- }
- // Have we been provided with integer arguments?
- if ( isIntegerArray( args ) ) {
- if ( nargs === 2 ) {
- a = args[ 0 ];
- b = args[ 1 ];
- if ( a < 0 ) {
- a = -a;
- }
- if ( b < 0 ) {
- b = -b;
- }
- if ( a <= MAXINT && b <= MAXINT ) {
- return bitwise( a, b );
- } else {
- return gcd( a, b );
- }
- }
- arr = args;
- }
- // If not integers, ensure the first argument is an array...
- else if ( !isArray( args[ 0 ] ) ) {
- throw new TypeError( 'gcd()::invalid input argument. Must provide an array of integers. Value: `' + args[ 0 ] + '`.' );
- }
- // Have we been provided with more than one argument? If so, ensure that the accessor argument is a function...
- else if ( nargs > 1 ) {
- arr = args[ 0 ];
- clbk = args[ 1 ];
- if ( !isFunction( clbk ) ) {
- throw new TypeError( 'gcd()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );
- }
- }
- // We have been provided an array...
- else {
- arr = args[ 0 ];
- }
- len = arr.length;
+ OrderedMap.prototype.remove = function remove (k) {
+ return updateOrderedMap(this, k, NOT_SET);
+ };
- // Check if a sufficient number of values have been provided...
- if ( len < 2 ) {
- return null;
- }
- // If an accessor is provided, extract the array values...
- if ( clbk ) {
- a = new Array( len );
- for ( i = 0; i < len; i++ ) {
- a[ i ] = clbk( arr[ i ], i );
- }
- arr = a;
- }
- // Given an input array, ensure all array values are integers...
- if ( nargs < 3 ) {
- if ( !isIntegerArray( arr ) ) {
- throw new TypeError( 'gcd()::invalid input argument. Accessed array values must be integers. Value: `' + arr + '`.' );
- }
- }
- // Convert any negative integers to positive integers...
- for ( i = 0; i < len; i++ ) {
- a = arr[ i ];
- if ( a < 0 ) {
- arr[ i ] = -a;
- }
- }
- // Exploit the fact that the gcd is an associative function...
- a = arr[ 0 ];
- for ( i = 1; i < len; i++ ) {
- b = arr[ i ];
- if ( b <= MAXINT && a <= MAXINT ) {
- a = bitwise( a, b );
- } else {
- a = gcd( a, b );
- }
- }
- return a;
-} // end FUNCTION compute()
+ OrderedMap.prototype.__iterate = function __iterate (fn, reverse) {
+ var this$1$1 = this;
+ return this._list.__iterate(
+ function (entry) { return entry && fn(entry[1], entry[0], this$1$1); },
+ reverse
+ );
+ };
-// EXPORTS //
+ OrderedMap.prototype.__iterator = function __iterator (type, reverse) {
+ return this._list.fromEntrySeq().__iterator(type, reverse);
+ };
-module.exports = compute;
+ OrderedMap.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+ if (ownerID === this.__ownerID) {
+ return this;
+ }
+ var newMap = this._map.__ensureOwner(ownerID);
+ var newList = this._list.__ensureOwner(ownerID);
+ if (!ownerID) {
+ if (this.size === 0) {
+ return emptyOrderedMap();
+ }
+ this.__ownerID = ownerID;
+ this.__altered = false;
+ this._map = newMap;
+ this._list = newList;
+ return this;
+ }
+ return makeOrderedMap(newMap, newList, ownerID, this.__hash);
+ };
+ return OrderedMap;
+}(Map));
-/***/ }),
-/* 13 */
-/***/ (function(module, exports, __webpack_require__) {
+OrderedMap.isOrderedMap = isOrderedMap;
-"use strict";
+OrderedMap.prototype[IS_ORDERED_SYMBOL] = true;
+OrderedMap.prototype[DELETE] = OrderedMap.prototype.remove;
+function makeOrderedMap(map, list, ownerID, hash) {
+ var omap = Object.create(OrderedMap.prototype);
+ omap.size = map ? map.size : 0;
+ omap._map = map;
+ omap._list = list;
+ omap.__ownerID = ownerID;
+ omap.__hash = hash;
+ omap.__altered = false;
+ return omap;
+}
-var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); /**
- * Lambdoma Triangle
- * @module index.js;
- */
+var EMPTY_ORDERED_MAP;
+function emptyOrderedMap() {
+ return (
+ EMPTY_ORDERED_MAP ||
+ (EMPTY_ORDERED_MAP = makeOrderedMap(emptyMap(), emptyList()))
+ );
+}
-var _computeGcd = __webpack_require__(12);
+function updateOrderedMap(omap, k, v) {
+ var map = omap._map;
+ var list = omap._list;
+ var i = map.get(k);
+ var has = i !== undefined;
+ var newMap;
+ var newList;
+ if (v === NOT_SET) {
+ // removed
+ if (!has) {
+ return omap;
+ }
+ if (list.size >= SIZE && list.size >= map.size * 2) {
+ newList = list.filter(function (entry, idx) { return entry !== undefined && i !== idx; });
+ newMap = newList
+ .toKeyedSeq()
+ .map(function (entry) { return entry[0]; })
+ .flip()
+ .toMap();
+ if (omap.__ownerID) {
+ newMap.__ownerID = newList.__ownerID = omap.__ownerID;
+ }
+ } else {
+ newMap = map.remove(k);
+ newList = i === list.size - 1 ? list.pop() : list.set(i, undefined);
+ }
+ } else if (has) {
+ if (v === list.get(i)[1]) {
+ return omap;
+ }
+ newMap = map;
+ newList = list.set(i, [k, v]);
+ } else {
+ newMap = map.set(k, list.size);
+ newList = list.set(list.size, [k, v]);
+ }
+ if (omap.__ownerID) {
+ omap.size = newMap.size;
+ omap._map = newMap;
+ omap._list = newList;
+ omap.__hash = undefined;
+ omap.__altered = true;
+ return omap;
+ }
+ return makeOrderedMap(newMap, newList);
+}
-var _computeGcd2 = _interopRequireDefault(_computeGcd);
+var IS_STACK_SYMBOL = '@@__IMMUTABLE_STACK__@@';
+/**
+ * True if `maybeStack` is a Stack.
+ */
+function isStack(maybeStack) {
+ return Boolean(maybeStack &&
+ // @ts-expect-error: maybeStack is typed as `{}`, need to change in 6.0 to `maybeStack && typeof maybeStack === 'object' && MAYBE_STACK_SYMBOL in maybeStack`
+ maybeStack[IS_STACK_SYMBOL]);
+}
-var _keys = __webpack_require__(6);
+var Stack = /*@__PURE__*/(function (IndexedCollection) {
+ function Stack(value) {
+ // eslint-disable-next-line no-constructor-return
+ return value === undefined || value === null
+ ? emptyStack()
+ : isStack(value)
+ ? value
+ : emptyStack().pushAll(value);
+ }
-var _keys2 = _interopRequireDefault(_keys);
+ if ( IndexedCollection ) Stack.__proto__ = IndexedCollection;
+ Stack.prototype = Object.create( IndexedCollection && IndexedCollection.prototype );
+ Stack.prototype.constructor = Stack;
-var _color = __webpack_require__(4);
+ Stack.of = function of (/*...values*/) {
+ return this(arguments);
+ };
-var _color2 = _interopRequireDefault(_color);
+ Stack.prototype.toString = function toString () {
+ return this.__toString('Stack [', ']');
+ };
-var _kalimba = __webpack_require__(5);
+ // @pragma Access
-var _kalimba2 = _interopRequireDefault(_kalimba);
+ Stack.prototype.get = function get (index, notSetValue) {
+ var head = this._head;
+ index = wrapIndex(this, index);
+ while (head && index--) {
+ head = head.next;
+ }
+ return head ? head.value : notSetValue;
+ };
-var _sampler = __webpack_require__(10);
+ Stack.prototype.peek = function peek () {
+ return this._head && this._head.value;
+ };
-var _sampler2 = _interopRequireDefault(_sampler);
+ // @pragma Modification
-var _organ = __webpack_require__(8);
+ Stack.prototype.push = function push (/*...values*/) {
+ var arguments$1 = arguments;
-var _organ2 = _interopRequireDefault(_organ);
+ if (arguments.length === 0) {
+ return this;
+ }
+ var newSize = this.size + arguments.length;
+ var head = this._head;
+ for (var ii = arguments.length - 1; ii >= 0; ii--) {
+ head = {
+ value: arguments$1[ii],
+ next: head,
+ };
+ }
+ if (this.__ownerID) {
+ this.size = newSize;
+ this._head = head;
+ this.__hash = undefined;
+ this.__altered = true;
+ return this;
+ }
+ return makeStack(newSize, head);
+ };
+
+ Stack.prototype.pushAll = function pushAll (iter) {
+ iter = IndexedCollection(iter);
+ if (iter.size === 0) {
+ return this;
+ }
+ if (this.size === 0 && isStack(iter)) {
+ return iter;
+ }
+ assertNotInfinite(iter.size);
+ var newSize = this.size;
+ var head = this._head;
+ iter.__iterate(function (value) {
+ newSize++;
+ head = {
+ value: value,
+ next: head,
+ };
+ }, /* reverse */ true);
+ if (this.__ownerID) {
+ this.size = newSize;
+ this._head = head;
+ this.__hash = undefined;
+ this.__altered = true;
+ return this;
+ }
+ return makeStack(newSize, head);
+ };
-var _midi = __webpack_require__(7);
+ Stack.prototype.pop = function pop () {
+ return this.slice(1);
+ };
-var _midi2 = _interopRequireDefault(_midi);
+ Stack.prototype.clear = function clear () {
+ if (this.size === 0) {
+ return this;
+ }
+ if (this.__ownerID) {
+ this.size = 0;
+ this._head = undefined;
+ this.__hash = undefined;
+ this.__altered = true;
+ return this;
+ }
+ return emptyStack();
+ };
+
+ Stack.prototype.slice = function slice (begin, end) {
+ if (wholeSlice(begin, end, this.size)) {
+ return this;
+ }
+ var resolvedBegin = resolveBegin(begin, this.size);
+ var resolvedEnd = resolveEnd(end, this.size);
+ if (resolvedEnd !== this.size) {
+ // super.slice(begin, end);
+ return IndexedCollection.prototype.slice.call(this, begin, end);
+ }
+ var newSize = this.size - resolvedBegin;
+ var head = this._head;
+ while (resolvedBegin--) {
+ head = head.next;
+ }
+ if (this.__ownerID) {
+ this.size = newSize;
+ this._head = head;
+ this.__hash = undefined;
+ this.__altered = true;
+ return this;
+ }
+ return makeStack(newSize, head);
+ };
-var _oktransition = __webpack_require__(637);
+ // @pragma Mutability
-var _oktransition2 = _interopRequireDefault(_oktransition);
+ Stack.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+ if (ownerID === this.__ownerID) {
+ return this;
+ }
+ if (!ownerID) {
+ if (this.size === 0) {
+ return emptyStack();
+ }
+ this.__ownerID = ownerID;
+ this.__altered = false;
+ return this;
+ }
+ return makeStack(this.size, this._head, ownerID, this.__hash);
+ };
-var _output = __webpack_require__(9);
+ // @pragma Iteration
-var _util = __webpack_require__(2);
+ Stack.prototype.__iterate = function __iterate (fn, reverse) {
+ var this$1$1 = this;
-var _scales = __webpack_require__(11);
+ if (reverse) {
+ return new ArraySeq(this.toArray()).__iterate(
+ function (v, k) { return fn(v, k, this$1$1); },
+ reverse
+ );
+ }
+ var iterations = 0;
+ var node = this._head;
+ while (node) {
+ if (fn(node.value, iterations++, this) === false) {
+ break;
+ }
+ node = node.next;
+ }
+ return iterations;
+ };
-function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+ Stack.prototype.__iterator = function __iterator (type, reverse) {
+ if (reverse) {
+ return new ArraySeq(this.toArray()).__iterator(type, reverse);
+ }
+ var iterations = 0;
+ var node = this._head;
+ return new Iterator(function () {
+ if (node) {
+ var value = node.value;
+ node = node.next;
+ return iteratorValue(type, iterations++, value);
+ }
+ return iteratorDone();
+ });
+ };
-var instrument = _kalimba2.default;
+ return Stack;
+}(IndexedCollection));
-var grid = document.createElement("grid");
-var root = 440;
-var s = 50;
-var w = void 0,
- h = void 0,
- ws = void 0,
- hs = void 0;
+Stack.isStack = isStack;
-var add_on = 0;
-var mul_on = 1.0;
-var add_off = 0.1;
-var mul_off = 0.9;
+var StackPrototype = Stack.prototype;
+StackPrototype[IS_STACK_SYMBOL] = true;
+StackPrototype.shift = StackPrototype.pop;
+StackPrototype.unshift = StackPrototype.push;
+StackPrototype.unshiftAll = StackPrototype.pushAll;
+StackPrototype.withMutations = withMutations;
+StackPrototype.wasAltered = wasAltered;
+StackPrototype.asImmutable = asImmutable;
+StackPrototype['@@transducer/init'] = StackPrototype.asMutable = asMutable;
+StackPrototype['@@transducer/step'] = function (result, arr) {
+ return result.unshift(arr);
+};
+StackPrototype['@@transducer/result'] = function (obj) {
+ return obj.asImmutable();
+};
-var dragging = false;
-var erasing = false;
-var lastNote = 0;
-var notes = [];
-var base_x = 0;
-var base_y = 0;
-var scaleMode = 0;
-var is_split = false;
-var intervals = void 0;
+function makeStack(size, head, ownerID, hash) {
+ var map = Object.create(StackPrototype);
+ map.size = size;
+ map._head = head;
+ map.__ownerID = ownerID;
+ map.__hash = hash;
+ map.__altered = false;
+ return map;
+}
-(0, _util.requestAudioContext)(function () {
- var output = (0, _output.getOutput)();
- document.body.appendChild(grid);
- _kalimba2.default.load(output);
- _organ2.default.load(output);
- _sampler2.default.load(output, function ready() {
- instrument = _sampler2.default;
- });
- build();
- bind();
-});
+var EMPTY_STACK;
+function emptyStack() {
+ return EMPTY_STACK || (EMPTY_STACK = makeStack(0));
+}
-function build() {
- w = window.innerWidth;
- h = window.innerHeight;
- ws = Math.ceil(w / s);
- hs = Math.ceil(h / s);
- var scale = _scales.scales[scaleMode % _scales.scales.length];
- if (scale.reset) {
- scale.reset(Math.round(base_x), Math.round(base_y), ws, hs);
- }
- for (var i = 0; i < ws; i++) {
- notes[i] = [];
- for (var j = 0; j < hs; j++) {
- notes[i][j] = add(i, j);
- }
- }
- log();
+var IS_SET_SYMBOL = '@@__IMMUTABLE_SET__@@';
+/**
+ * True if `maybeSet` is a Set.
+ *
+ * Also true for OrderedSets.
+ */
+function isSet(maybeSet) {
+ return Boolean(maybeSet &&
+ // @ts-expect-error: maybeSet is typed as `{}`, need to change in 6.0 to `maybeSeq && typeof maybeSet === 'object' && MAYBE_SET_SYMBOL in maybeSet`
+ maybeSet[IS_SET_SYMBOL]);
}
-function rebuild() {
- notes.forEach(function (row) {
- return row.forEach(function (note) {
- return note.destroy();
- });
- });
- build();
+
+/**
+ * True if `maybeOrderedSet` is an OrderedSet.
+ */
+function isOrderedSet(maybeOrderedSet) {
+ return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet);
}
-function log() {
- var seen = {};
- // console.log(notes);
- for (var i = 0; i < 8; i++) {
- for (var j = 0; j < 8; j++) {
- var interval = notes[i][j].interval;
- var rounded = (0, _util.roundInterval)(interval);
- if (!seen[rounded] && (0, _util.intervalInRange)(interval, root)) {
- seen[rounded] = notes[i][j].interval;
- }
+
+function deepEqual(a, b) {
+ if (a === b) {
+ return true;
}
- }
- intervals = Object.values(seen).sort(function (a, b) {
- return a - b;
- });
- // console.log(intervals);
- console.log(intervals.length, "unique intervals in 8x8");
-}
-function play(note) {
- if (!_organ2.default.isPlaying(note.interval)) {
- var interval = note.interval;
- // while (interval < root) {
- // interval *= 2;
- // }
- // while (interval > root) {
- // interval /= 2;
- // }
- var rounded = (0, _util.roundInterval)(note.interval);
- _organ2.default.play(interval);
- notes.forEach(function (row) {
- return row.forEach(function (note) {
- return note.rounded === rounded && note.div.classList.add("playing");
- });
+ if (!isCollection(b) ||
+ // @ts-expect-error size should exists on Collection
+ (a.size !== undefined && b.size !== undefined && a.size !== b.size) ||
+ // @ts-expect-error __hash exists on Collection
+ (a.__hash !== undefined &&
+ // @ts-expect-error __hash exists on Collection
+ b.__hash !== undefined &&
+ // @ts-expect-error __hash exists on Collection
+ a.__hash !== b.__hash) ||
+ isKeyed(a) !== isKeyed(b) ||
+ isIndexed(a) !== isIndexed(b) ||
+ // @ts-expect-error Range extends Collection, which implements [Symbol.iterator], so it is valid
+ isOrdered(a) !== isOrdered(b)) {
+ return false;
+ }
+ // @ts-expect-error size should exists on Collection
+ if (a.size === 0 && b.size === 0) {
+ return true;
+ }
+ var notAssociative = !isAssociative(a);
+ // @ts-expect-error Range extends Collection, which implements [Symbol.iterator], so it is valid
+ if (isOrdered(a)) {
+ var entries = a.entries();
+ // @ts-expect-error need to cast as boolean
+ return (b.every(function (v, k) {
+ var entry = entries.next().value;
+ return entry && is(entry[1], v) && (notAssociative || is(entry[0], k));
+ }) && entries.next().done);
+ }
+ var flipped = false;
+ if (a.size === undefined) {
+ // @ts-expect-error size should exists on Collection
+ if (b.size === undefined) {
+ if (typeof a.cacheResult === 'function') {
+ a.cacheResult();
+ }
+ }
+ else {
+ flipped = true;
+ var _ = a;
+ a = b;
+ b = _;
+ }
+ }
+ var allEqual = true;
+ var bSize =
+ // @ts-expect-error b is Range | Repeat | Collection
+ * 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 connect.
+ *
+ * @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).
+ *
+ *
+ *
+ *
+ * @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.
+ *
+ *
+ * @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 connect.
+ *
+ * @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 connect.
+ *
+ * @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.
+ *
+ *
+ * @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:
+ *
+ *
+ * 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 input[0]
+ * and input[1]. 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 input[1] from the signal connected
+ * to input[0]. If an argument is provided in the constructor, the
+ * signals .value 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.
+ * 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 input[0].
+ * @type {Tone.Gain}
+ */
+ this.a = this.input[0] = new Tone.Gain();
+ /**
+ * Alias for input[1].
+ * @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% input[0] and
+ * a value of 1 will output 100% input[1].
+ * @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 output[0]
+ * @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 output[1]
+ * @type {Tone.Filter}
+ */
+ this.mid = this.output[1] = new Tone.Filter(0, 'lowpass');
+ /**
+ * The high band output. Alias for output[2]
+ * @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 min and
+ * max 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: setStateAtTime("state", time)
+ * and getValueAtTime(time).
+ *
+ * @extends {Tone.Timeline}
+ * @param {String} initial The initial state of the TimelineState.
+ * Defaults to undefined
+ */
+ 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.
+ * A single transport is created for you when the library is initialized.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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 input[0]
+ * @type {GainNode}
+ */
+ this.left = this.input[0] = new Tone.Gain();
+ /**
+ * The right input channel.
+ * Alias for input[1].
+ * @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 output[0]
+ * @type {Tone.Gain}
+ */
+ this.left = this.output[0] = new Tone.Gain();
+ /**
+ * Right channel output.
+ * Alias for output[1]
+ * @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).
+ *
+ * Mid = (Left+Right)/sqrt(2); // obtain mid-signal from left and right
+ *
+ * @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
+ *
+ * Side = (Left-Right)/sqrt(2); // obtain side-signal from left and righ
+ * output[0]
+ * @type {Tone.Expr}
+ */
+ this.mid = this.output[0] = new Tone.Expr('($0 + $1) * $2');
+ /**
+ * The side output. Connect to side processing. Alias for
+ * output[1]
+ * @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.
+ *
+ * Left = (Mid+Side)/sqrt(2); // obtain left signal from mid and side
+ *
+ * @extends {Tone.StereoEffect}
+ * @constructor
+ */
+ Tone.MidSideMerge = function () {
+ this.createInsOuts(2, 0);
+ /**
+ * The mid signal input. Alias for
+ *
+ * Right = (Mid-Side)/sqrt(2); // obtain right signal from mid and side
+ * input[0]
+ * @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
+ * input[1]
+ * @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.
+ *
+ *
+ * @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.
+ *
+ * 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.
+ *
+ * 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:
+ * order 2: 2x^2 + 1
+ * order 3: 4x^3 + 3x
+ * @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).
+ *
+ * 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).
+ *
+ *
+ * Mid *= 2*(1-width)
+ *
+ * @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.
+ *
+ * Side *= 2*width
+ *
+ *
+ * @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).
+ *
+ *
+ * @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.
+ *
+ *
+ * @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.
+ *
+ *
+ * @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).
+ *
+ *
+ * @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
note * .octaves and ramps to
+ * note over the duration of .pitchDecay.
+ *
+ * @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.
+ *
+ *
+ * @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;
+}));
/***/ }),
-/* 90 */
+/* 109 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var aCallable = __webpack_require__(42);
-
-var $TypeError = TypeError;
-
-var PromiseCapability = function (C) {
- var resolve, reject;
- this.promise = new C(function ($$resolve, $$reject) {
- if (resolve !== undefined || reject !== undefined) throw new $TypeError('Bad Promise constructor');
- resolve = $$resolve;
- reject = $$reject;
- });
- this.resolve = aCallable(resolve);
- this.reject = aCallable(reject);
-};
+var charAt = __webpack_require__(134).charAt;
-// `NewPromiseCapability` abstract operation
-// https://tc39.es/ecma262/#sec-newpromisecapability
-module.exports.f = function (C) {
- return new PromiseCapability(C);
+// `AdvanceStringIndex` abstract operation
+// https://tc39.es/ecma262/#sec-advancestringindex
+module.exports = function (S, index, unicode) {
+ return index + (unicode ? charAt(S, index).length : 1);
};
/***/ }),
-/* 91 */
+/* 110 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var toIntegerOrInfinity = __webpack_require__(54);
-
-var max = Math.max;
-var min = Math.min;
-
-// Helper for a popular repeating case of the spec:
-// Let integer be ? ToInteger(index).
-// If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
-module.exports = function (index, length) {
- var integer = toIntegerOrInfinity(index);
- return integer < 0 ? max(integer + length, 0) : min(integer, length);
-};
+// eslint-disable-next-line es/no-typed-arrays -- safe
+module.exports = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';
/***/ }),
-/* 92 */
+/* 111 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var $ = __webpack_require__(32);
-var globalThis = __webpack_require__(35);
-var call = __webpack_require__(36);
-var DESCRIPTORS = __webpack_require__(38);
-var TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS = __webpack_require__(208);
-var ArrayBufferViewCore = __webpack_require__(44);
-var ArrayBufferModule = __webpack_require__(141);
-var anInstance = __webpack_require__(71);
-var createPropertyDescriptor = __webpack_require__(73);
-var createNonEnumerableProperty = __webpack_require__(59);
-var isIntegralNumber = __webpack_require__(188);
-var toLength = __webpack_require__(77);
-var toIndex = __webpack_require__(169);
-var toOffset = __webpack_require__(276);
-var toUint8Clamped = __webpack_require__(313);
-var toPropertyKey = __webpack_require__(94);
-var hasOwn = __webpack_require__(45);
-var classof = __webpack_require__(79);
-var isObject = __webpack_require__(40);
-var isSymbol = __webpack_require__(104);
-var create = __webpack_require__(62);
-var isPrototypeOf = __webpack_require__(68);
-var setPrototypeOf = __webpack_require__(81);
-var getOwnPropertyNames = __webpack_require__(106).f;
-var typedArrayFrom = __webpack_require__(277);
-var forEach = __webpack_require__(58).forEach;
-var setSpecies = __webpack_require__(122);
-var defineBuiltInAccessor = __webpack_require__(55);
-var definePropertyModule = __webpack_require__(51);
-var getOwnPropertyDescriptorModule = __webpack_require__(63);
-var arrayFromConstructorAndList = __webpack_require__(142);
-var InternalStateModule = __webpack_require__(53);
-var inheritIfRequired = __webpack_require__(101);
+var globalThis = __webpack_require__(3);
+var uncurryThis = __webpack_require__(2);
+var DESCRIPTORS = __webpack_require__(6);
+var NATIVE_ARRAY_BUFFER = __webpack_require__(110);
+var FunctionName = __webpack_require__(82);
+var createNonEnumerableProperty = __webpack_require__(27);
+var defineBuiltInAccessor = __webpack_require__(23);
+var defineBuiltIns = __webpack_require__(56);
+var fails = __webpack_require__(1);
+var anInstance = __webpack_require__(39);
+var toIntegerOrInfinity = __webpack_require__(22);
+var toLength = __webpack_require__(45);
+var toIndex = __webpack_require__(139);
+var fround = __webpack_require__(220);
+var IEEE754 = __webpack_require__(296);
+var getPrototypeOf = __webpack_require__(35);
+var setPrototypeOf = __webpack_require__(49);
+var arrayFill = __webpack_require__(146);
+var arraySlice = __webpack_require__(46);
+var inheritIfRequired = __webpack_require__(70);
+var copyConstructorProperties = __webpack_require__(79);
+var setToStringTag = __webpack_require__(38);
+var InternalStateModule = __webpack_require__(21);
-var getInternalState = InternalStateModule.get;
+var PROPER_FUNCTION_NAME = FunctionName.PROPER;
+var CONFIGURABLE_FUNCTION_NAME = FunctionName.CONFIGURABLE;
+var ARRAY_BUFFER = 'ArrayBuffer';
+var DATA_VIEW = 'DataView';
+var PROTOTYPE = 'prototype';
+var WRONG_LENGTH = 'Wrong length';
+var WRONG_INDEX = 'Wrong index';
+var getInternalArrayBufferState = InternalStateModule.getterFor(ARRAY_BUFFER);
+var getInternalDataViewState = InternalStateModule.getterFor(DATA_VIEW);
var setInternalState = InternalStateModule.set;
-var enforceInternalState = InternalStateModule.enforce;
-var nativeDefineProperty = definePropertyModule.f;
-var nativeGetOwnPropertyDescriptor = getOwnPropertyDescriptorModule.f;
+var NativeArrayBuffer = globalThis[ARRAY_BUFFER];
+var $ArrayBuffer = NativeArrayBuffer;
+var ArrayBufferPrototype = $ArrayBuffer && $ArrayBuffer[PROTOTYPE];
+var $DataView = globalThis[DATA_VIEW];
+var DataViewPrototype = $DataView && $DataView[PROTOTYPE];
+var ObjectPrototype = Object.prototype;
+var Array = globalThis.Array;
var RangeError = globalThis.RangeError;
-var ArrayBuffer = ArrayBufferModule.ArrayBuffer;
-var ArrayBufferPrototype = ArrayBuffer.prototype;
-var DataView = ArrayBufferModule.DataView;
-var NATIVE_ARRAY_BUFFER_VIEWS = ArrayBufferViewCore.NATIVE_ARRAY_BUFFER_VIEWS;
-var TYPED_ARRAY_TAG = ArrayBufferViewCore.TYPED_ARRAY_TAG;
-var TypedArray = ArrayBufferViewCore.TypedArray;
-var TypedArrayPrototype = ArrayBufferViewCore.TypedArrayPrototype;
-var isTypedArray = ArrayBufferViewCore.isTypedArray;
-var BYTES_PER_ELEMENT = 'BYTES_PER_ELEMENT';
-var WRONG_LENGTH = 'Wrong length';
-
-var addGetter = function (it, key) {
- defineBuiltInAccessor(it, key, {
- configurable: true,
- get: function () {
- return getInternalState(this)[key];
- }
- });
-};
-
-var isArrayBuffer = function (it) {
- var klass;
- return isPrototypeOf(ArrayBufferPrototype, it) || (klass = classof(it)) === 'ArrayBuffer' || klass === 'SharedArrayBuffer';
-};
-
-var isTypedArrayIndex = function (target, key) {
- return isTypedArray(target)
- && !isSymbol(key)
- && key in target
- && isIntegralNumber(+key)
- && key >= 0;
-};
-
-var wrappedGetOwnPropertyDescriptor = function getOwnPropertyDescriptor(target, key) {
- key = toPropertyKey(key);
- return isTypedArrayIndex(target, key)
- ? createPropertyDescriptor(2, target[key])
- : nativeGetOwnPropertyDescriptor(target, key);
-};
-
-var wrappedDefineProperty = function defineProperty(target, key, descriptor) {
- key = toPropertyKey(key);
- if (isTypedArrayIndex(target, key)
- && isObject(descriptor)
- && hasOwn(descriptor, 'value')
- && !hasOwn(descriptor, 'get')
- && !hasOwn(descriptor, 'set')
- // TODO: add validation descriptor w/o calling accessors
- && !descriptor.configurable
- && (!hasOwn(descriptor, 'writable') || descriptor.writable)
- && (!hasOwn(descriptor, 'enumerable') || descriptor.enumerable)
- ) {
- target[key] = descriptor.value;
- return target;
- } return nativeDefineProperty(target, key, descriptor);
-};
-
-if (DESCRIPTORS) {
- if (!NATIVE_ARRAY_BUFFER_VIEWS) {
- getOwnPropertyDescriptorModule.f = wrappedGetOwnPropertyDescriptor;
- definePropertyModule.f = wrappedDefineProperty;
- addGetter(TypedArrayPrototype, 'buffer');
- addGetter(TypedArrayPrototype, 'byteOffset');
- addGetter(TypedArrayPrototype, 'byteLength');
- addGetter(TypedArrayPrototype, 'length');
- }
-
- $({ target: 'Object', stat: true, forced: !NATIVE_ARRAY_BUFFER_VIEWS }, {
- getOwnPropertyDescriptor: wrappedGetOwnPropertyDescriptor,
- defineProperty: wrappedDefineProperty
- });
-
- module.exports = function (TYPE, wrapper, CLAMPED) {
- var BYTES = TYPE.match(/\d+/)[0] / 8;
- var CONSTRUCTOR_NAME = TYPE + (CLAMPED ? 'Clamped' : '') + 'Array';
- var GETTER = 'get' + TYPE;
- var SETTER = 'set' + TYPE;
- var NativeTypedArrayConstructor = globalThis[CONSTRUCTOR_NAME];
- var TypedArrayConstructor = NativeTypedArrayConstructor;
- var TypedArrayConstructorPrototype = TypedArrayConstructor && TypedArrayConstructor.prototype;
- var exported = {};
-
- var getter = function (that, index) {
- var data = getInternalState(that);
- return data.view[GETTER](index * BYTES + data.byteOffset, true);
- };
-
- var setter = function (that, index, value) {
- var data = getInternalState(that);
- data.view[SETTER](index * BYTES + data.byteOffset, CLAMPED ? toUint8Clamped(value) : value, true);
- };
-
- var addElement = function (that, index) {
- nativeDefineProperty(that, index, {
- get: function () {
- return getter(this, index);
- },
- set: function (value) {
- return setter(this, index, value);
- },
- enumerable: true
- });
- };
-
- if (!NATIVE_ARRAY_BUFFER_VIEWS) {
- TypedArrayConstructor = wrapper(function (that, data, offset, $length) {
- anInstance(that, TypedArrayConstructorPrototype);
- var index = 0;
- var byteOffset = 0;
- var buffer, byteLength, length;
- if (!isObject(data)) {
- length = toIndex(data);
- byteLength = length * BYTES;
- buffer = new ArrayBuffer(byteLength);
- } else if (isArrayBuffer(data)) {
- buffer = data;
- byteOffset = toOffset(offset, BYTES);
- var $len = data.byteLength;
- if ($length === undefined) {
- if ($len % BYTES) throw new RangeError(WRONG_LENGTH);
- byteLength = $len - byteOffset;
- if (byteLength < 0) throw new RangeError(WRONG_LENGTH);
- } else {
- byteLength = toLength($length) * BYTES;
- if (byteLength + byteOffset > $len) throw new RangeError(WRONG_LENGTH);
- }
- length = byteLength / BYTES;
- } else if (isTypedArray(data)) {
- return arrayFromConstructorAndList(TypedArrayConstructor, data);
- } else {
- return call(typedArrayFrom, TypedArrayConstructor, data);
- }
- setInternalState(that, {
- buffer: buffer,
- byteOffset: byteOffset,
- byteLength: byteLength,
- length: length,
- view: new DataView(buffer)
- });
- while (index < length) addElement(that, index++);
- });
-
- if (setPrototypeOf) setPrototypeOf(TypedArrayConstructor, TypedArray);
- TypedArrayConstructorPrototype = TypedArrayConstructor.prototype = create(TypedArrayPrototype);
- } else if (TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS) {
- TypedArrayConstructor = wrapper(function (dummy, data, typedArrayOffset, $length) {
- anInstance(dummy, TypedArrayConstructorPrototype);
- return inheritIfRequired(function () {
- if (!isObject(data)) return new NativeTypedArrayConstructor(toIndex(data));
- if (isArrayBuffer(data)) return $length !== undefined
- ? new NativeTypedArrayConstructor(data, toOffset(typedArrayOffset, BYTES), $length)
- : typedArrayOffset !== undefined
- ? new NativeTypedArrayConstructor(data, toOffset(typedArrayOffset, BYTES))
- : new NativeTypedArrayConstructor(data);
- if (isTypedArray(data)) return arrayFromConstructorAndList(TypedArrayConstructor, data);
- return call(typedArrayFrom, TypedArrayConstructor, data);
- }(), dummy, TypedArrayConstructor);
- });
-
- if (setPrototypeOf) setPrototypeOf(TypedArrayConstructor, TypedArray);
- forEach(getOwnPropertyNames(NativeTypedArrayConstructor), function (key) {
- if (!(key in TypedArrayConstructor)) {
- createNonEnumerableProperty(TypedArrayConstructor, key, NativeTypedArrayConstructor[key]);
- }
- });
- TypedArrayConstructor.prototype = TypedArrayConstructorPrototype;
- }
-
- if (TypedArrayConstructorPrototype.constructor !== TypedArrayConstructor) {
- createNonEnumerableProperty(TypedArrayConstructorPrototype, 'constructor', TypedArrayConstructor);
- }
-
- enforceInternalState(TypedArrayConstructorPrototype).TypedArrayConstructor = TypedArrayConstructor;
-
- if (TYPED_ARRAY_TAG) {
- createNonEnumerableProperty(TypedArrayConstructorPrototype, TYPED_ARRAY_TAG, CONSTRUCTOR_NAME);
- }
-
- var FORCED = TypedArrayConstructor !== NativeTypedArrayConstructor;
-
- exported[CONSTRUCTOR_NAME] = TypedArrayConstructor;
-
- $({ global: true, constructor: true, forced: FORCED, sham: !NATIVE_ARRAY_BUFFER_VIEWS }, exported);
-
- if (!(BYTES_PER_ELEMENT in TypedArrayConstructor)) {
- createNonEnumerableProperty(TypedArrayConstructor, BYTES_PER_ELEMENT, BYTES);
- }
-
- if (!(BYTES_PER_ELEMENT in TypedArrayConstructorPrototype)) {
- createNonEnumerableProperty(TypedArrayConstructorPrototype, BYTES_PER_ELEMENT, BYTES);
- }
-
- setSpecies(CONSTRUCTOR_NAME);
- };
-} else module.exports = function () { /* empty */ };
-
-
-/***/ }),
-/* 93 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var classof = __webpack_require__(64);
-
-// `IsArray` abstract operation
-// https://tc39.es/ecma262/#sec-isarray
-// eslint-disable-next-line es/no-array-isarray -- safe
-module.exports = Array.isArray || function isArray(argument) {
- return classof(argument) === 'Array';
-};
-
-
-/***/ }),
-/* 94 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var toPrimitive = __webpack_require__(170);
-var isSymbol = __webpack_require__(104);
-
-// `ToPropertyKey` abstract operation
-// https://tc39.es/ecma262/#sec-topropertykey
-module.exports = function (argument) {
- var key = toPrimitive(argument, 'string');
- return isSymbol(key) ? key : key + '';
-};
-
-
-/***/ }),
-/* 95 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var has = __webpack_require__(82).has;
-
-// Perform ? RequireInternalSlot(M, [[SetData]])
-module.exports = function (it) {
- has(it);
- return it;
-};
-
-
-/***/ }),
-/* 96 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-// `CreateIterResultObject` abstract operation
-// https://tc39.es/ecma262/#sec-createiterresultobject
-module.exports = function (value, done) {
- return { value: value, done: done };
-};
-
-
-/***/ }),
-/* 97 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var $TypeError = TypeError;
-var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF; // 2 ** 53 - 1 == 9007199254740991
-
-module.exports = function (it) {
- if (it > MAX_SAFE_INTEGER) throw $TypeError('Maximum allowed index exceeded');
- return it;
-};
-
-
-/***/ }),
-/* 98 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var classofRaw = __webpack_require__(64);
-var uncurryThis = __webpack_require__(34);
-
-module.exports = function (fn) {
- // Nashorn bug:
- // https://github.com/zloirock/core-js/issues/1128
- // https://github.com/zloirock/core-js/issues/1130
- if (classofRaw(fn) === 'Function') return uncurryThis(fn);
-};
-
-
-/***/ }),
-/* 99 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var classof = __webpack_require__(79);
-var getMethod = __webpack_require__(60);
-var isNullOrUndefined = __webpack_require__(89);
-var Iterators = __webpack_require__(133);
-var wellKnownSymbol = __webpack_require__(39);
-
-var ITERATOR = wellKnownSymbol('iterator');
-
-module.exports = function (it) {
- if (!isNullOrUndefined(it)) return getMethod(it, ITERATOR)
- || getMethod(it, '@@iterator')
- || Iterators[classof(it)];
-};
-
-
-/***/ }),
-/* 100 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var aCallable = __webpack_require__(42);
-var anObject = __webpack_require__(37);
-var call = __webpack_require__(36);
-var toIntegerOrInfinity = __webpack_require__(54);
-var getIteratorDirect = __webpack_require__(65);
-
-var INVALID_SIZE = 'Invalid size';
-var $RangeError = RangeError;
-var $TypeError = TypeError;
-var max = Math.max;
-
-var SetRecord = function (set, intSize) {
- this.set = set;
- this.size = max(intSize, 0);
- this.has = aCallable(set.has);
- this.keys = aCallable(set.keys);
-};
-
-SetRecord.prototype = {
- getIterator: function () {
- return getIteratorDirect(anObject(call(this.keys, this.set)));
- },
- includes: function (it) {
- return call(this.has, this.set, it);
- }
-};
-
-// `GetSetRecord` abstract operation
-// https://tc39.es/proposal-set-methods/#sec-getsetrecord
-module.exports = function (obj) {
- anObject(obj);
- var numSize = +obj.size;
- // NOTE: If size is undefined, then numSize will be NaN
- // eslint-disable-next-line no-self-compare -- NaN check
- if (numSize !== numSize) throw new $TypeError(INVALID_SIZE);
- var intSize = toIntegerOrInfinity(numSize);
- if (intSize < 0) throw new $RangeError(INVALID_SIZE);
- return new SetRecord(obj, intSize);
-};
-
-
-/***/ }),
-/* 101 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var isCallable = __webpack_require__(46);
-var isObject = __webpack_require__(40);
-var setPrototypeOf = __webpack_require__(81);
-
-// makes subclassing work correct for wrapped built-ins
-module.exports = function ($this, dummy, Wrapper) {
- var NewTarget, NewTargetPrototype;
- if (
- // it can work only with native `setPrototypeOf`
- setPrototypeOf &&
- // we haven't completely correct pre-ES6 way for getting `new.target`, so use this
- isCallable(NewTarget = dummy.constructor) &&
- NewTarget !== Wrapper &&
- isObject(NewTargetPrototype = NewTarget.prototype) &&
- NewTargetPrototype !== Wrapper.prototype
- ) setPrototypeOf($this, NewTargetPrototype);
- return $this;
-};
-
-
-/***/ }),
-/* 102 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var $ = __webpack_require__(32);
-var uncurryThis = __webpack_require__(34);
-var hiddenKeys = __webpack_require__(131);
-var isObject = __webpack_require__(40);
-var hasOwn = __webpack_require__(45);
-var defineProperty = __webpack_require__(51).f;
-var getOwnPropertyNamesModule = __webpack_require__(106);
-var getOwnPropertyNamesExternalModule = __webpack_require__(195);
-var isExtensible = __webpack_require__(196);
-var uid = __webpack_require__(126);
-var FREEZING = __webpack_require__(112);
+var fill = uncurryThis(arrayFill);
+var reverse = uncurryThis([].reverse);
-var REQUIRED = false;
-var METADATA = uid('meta');
-var id = 0;
+var packIEEE754 = IEEE754.pack;
+var unpackIEEE754 = IEEE754.unpack;
-var setMetadata = function (it) {
- defineProperty(it, METADATA, { value: {
- objectID: 'O' + id++, // object ID
- weakData: {} // weak collections IDs
- } });
+var packInt8 = function (number) {
+ return [number & 0xFF];
};
-var fastKey = function (it, create) {
- // return a primitive with prefix
- if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
- if (!hasOwn(it, METADATA)) {
- // can't set metadata to uncaught frozen object
- if (!isExtensible(it)) return 'F';
- // not necessary to add metadata
- if (!create) return 'E';
- // add missing metadata
- setMetadata(it);
- // return object ID
- } return it[METADATA].objectID;
+var packInt16 = function (number) {
+ return [number & 0xFF, number >> 8 & 0xFF];
};
-var getWeakData = function (it, create) {
- if (!hasOwn(it, METADATA)) {
- // can't set metadata to uncaught frozen object
- if (!isExtensible(it)) return true;
- // not necessary to add metadata
- if (!create) return false;
- // add missing metadata
- setMetadata(it);
- // return the store of weak collections IDs
- } return it[METADATA].weakData;
+var packInt32 = function (number) {
+ return [number & 0xFF, number >> 8 & 0xFF, number >> 16 & 0xFF, number >> 24 & 0xFF];
};
-// add metadata on freeze-family methods calling
-var onFreeze = function (it) {
- if (FREEZING && REQUIRED && isExtensible(it) && !hasOwn(it, METADATA)) setMetadata(it);
- return it;
+var unpackInt32 = function (buffer) {
+ return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
};
-var enable = function () {
- meta.enable = function () { /* empty */ };
- REQUIRED = true;
- var getOwnPropertyNames = getOwnPropertyNamesModule.f;
- var splice = uncurryThis([].splice);
- var test = {};
- test[METADATA] = 1;
-
- // prevent exposing of metadata key
- if (getOwnPropertyNames(test).length) {
- getOwnPropertyNamesModule.f = function (it) {
- var result = getOwnPropertyNames(it);
- for (var i = 0, length = result.length; i < length; i++) {
- if (result[i] === METADATA) {
- splice(result, i, 1);
- break;
- }
- } return result;
- };
-
- $({ target: 'Object', stat: true, forced: true }, {
- getOwnPropertyNames: getOwnPropertyNamesExternalModule.f
- });
- }
+var packFloat32 = function (number) {
+ return packIEEE754(fround(number), 23, 4);
};
-var meta = module.exports = {
- enable: enable,
- fastKey: fastKey,
- getWeakData: getWeakData,
- onFreeze: onFreeze
+var packFloat64 = function (number) {
+ return packIEEE754(number, 52, 8);
};
-hiddenKeys[METADATA] = true;
+var addGetter = function (Constructor, key, getInternalState) {
+ defineBuiltInAccessor(Constructor[PROTOTYPE], key, {
+ configurable: true,
+ get: function () {
+ return getInternalState(this)[key];
+ }
+ });
+};
+var get = function (view, count, index, isLittleEndian) {
+ var store = getInternalDataViewState(view);
+ var intIndex = toIndex(index);
+ var boolIsLittleEndian = !!isLittleEndian;
+ if (intIndex + count > store.byteLength) throw new RangeError(WRONG_INDEX);
+ var bytes = store.bytes;
+ var start = intIndex + store.byteOffset;
+ var pack = arraySlice(bytes, start, start + count);
+ return boolIsLittleEndian ? pack : reverse(pack);
+};
-/***/ }),
-/* 103 */
-/***/ (function(module, exports, __webpack_require__) {
+var set = function (view, count, index, conversion, value, isLittleEndian) {
+ var store = getInternalDataViewState(view);
+ var intIndex = toIndex(index);
+ var pack = conversion(+value);
+ var boolIsLittleEndian = !!isLittleEndian;
+ if (intIndex + count > store.byteLength) throw new RangeError(WRONG_INDEX);
+ var bytes = store.bytes;
+ var start = intIndex + store.byteOffset;
+ for (var i = 0; i < count; i++) bytes[start + i] = pack[boolIsLittleEndian ? i : count - i - 1];
+};
-"use strict";
+if (!NATIVE_ARRAY_BUFFER) {
+ $ArrayBuffer = function ArrayBuffer(length) {
+ anInstance(this, ArrayBufferPrototype);
+ var byteLength = toIndex(length);
+ setInternalState(this, {
+ type: ARRAY_BUFFER,
+ bytes: fill(Array(byteLength), 0),
+ byteLength: byteLength
+ });
+ if (!DESCRIPTORS) {
+ this.byteLength = byteLength;
+ this.detached = false;
+ }
+ };
-var uncurryThis = __webpack_require__(34);
-var fails = __webpack_require__(33);
-var isCallable = __webpack_require__(46);
-var classof = __webpack_require__(79);
-var getBuiltIn = __webpack_require__(43);
-var inspectSource = __webpack_require__(186);
+ ArrayBufferPrototype = $ArrayBuffer[PROTOTYPE];
-var noop = function () { /* empty */ };
-var construct = getBuiltIn('Reflect', 'construct');
-var constructorRegExp = /^\s*(?:class|function)\b/;
-var exec = uncurryThis(constructorRegExp.exec);
-var INCORRECT_TO_STRING = !constructorRegExp.test(noop);
+ $DataView = function DataView(buffer, byteOffset, byteLength) {
+ anInstance(this, DataViewPrototype);
+ anInstance(buffer, ArrayBufferPrototype);
+ var bufferState = getInternalArrayBufferState(buffer);
+ var bufferLength = bufferState.byteLength;
+ var offset = toIntegerOrInfinity(byteOffset);
+ if (offset < 0 || offset > bufferLength) throw new RangeError('Wrong offset');
+ byteLength = byteLength === undefined ? bufferLength - offset : toLength(byteLength);
+ if (offset + byteLength > bufferLength) throw new RangeError(WRONG_LENGTH);
+ setInternalState(this, {
+ type: DATA_VIEW,
+ buffer: buffer,
+ byteLength: byteLength,
+ byteOffset: offset,
+ bytes: bufferState.bytes
+ });
+ if (!DESCRIPTORS) {
+ this.buffer = buffer;
+ this.byteLength = byteLength;
+ this.byteOffset = offset;
+ }
+ };
-var isConstructorModern = function isConstructor(argument) {
- if (!isCallable(argument)) return false;
- try {
- construct(noop, [], argument);
- return true;
- } catch (error) {
- return false;
- }
-};
+ DataViewPrototype = $DataView[PROTOTYPE];
-var isConstructorLegacy = function isConstructor(argument) {
- if (!isCallable(argument)) return false;
- switch (classof(argument)) {
- case 'AsyncFunction':
- case 'GeneratorFunction':
- case 'AsyncGeneratorFunction': return false;
- }
- try {
- // we can't check .prototype since constructors produced by .bind haven't it
- // `Function#toString` throws on some built-it function in some legacy engines
- // (for example, `DOMQuad` and similar in FF41-)
- return INCORRECT_TO_STRING || !!exec(constructorRegExp, inspectSource(argument));
- } catch (error) {
- return true;
+ if (DESCRIPTORS) {
+ addGetter($ArrayBuffer, 'byteLength', getInternalArrayBufferState);
+ addGetter($DataView, 'buffer', getInternalDataViewState);
+ addGetter($DataView, 'byteLength', getInternalDataViewState);
+ addGetter($DataView, 'byteOffset', getInternalDataViewState);
}
-};
-isConstructorLegacy.sham = true;
+ defineBuiltIns(DataViewPrototype, {
+ getInt8: function getInt8(byteOffset) {
+ return get(this, 1, byteOffset)[0] << 24 >> 24;
+ },
+ getUint8: function getUint8(byteOffset) {
+ return get(this, 1, byteOffset)[0];
+ },
+ getInt16: function getInt16(byteOffset /* , littleEndian */) {
+ var bytes = get(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : false);
+ return (bytes[1] << 8 | bytes[0]) << 16 >> 16;
+ },
+ getUint16: function getUint16(byteOffset /* , littleEndian */) {
+ var bytes = get(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : false);
+ return bytes[1] << 8 | bytes[0];
+ },
+ getInt32: function getInt32(byteOffset /* , littleEndian */) {
+ return unpackInt32(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false));
+ },
+ getUint32: function getUint32(byteOffset /* , littleEndian */) {
+ return unpackInt32(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false)) >>> 0;
+ },
+ getFloat32: function getFloat32(byteOffset /* , littleEndian */) {
+ return unpackIEEE754(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false), 23);
+ },
+ getFloat64: function getFloat64(byteOffset /* , littleEndian */) {
+ return unpackIEEE754(get(this, 8, byteOffset, arguments.length > 1 ? arguments[1] : false), 52);
+ },
+ setInt8: function setInt8(byteOffset, value) {
+ set(this, 1, byteOffset, packInt8, value);
+ },
+ setUint8: function setUint8(byteOffset, value) {
+ set(this, 1, byteOffset, packInt8, value);
+ },
+ setInt16: function setInt16(byteOffset, value /* , littleEndian */) {
+ set(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : false);
+ },
+ setUint16: function setUint16(byteOffset, value /* , littleEndian */) {
+ set(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : false);
+ },
+ setInt32: function setInt32(byteOffset, value /* , littleEndian */) {
+ set(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : false);
+ },
+ setUint32: function setUint32(byteOffset, value /* , littleEndian */) {
+ set(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : false);
+ },
+ setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) {
+ set(this, 4, byteOffset, packFloat32, value, arguments.length > 2 ? arguments[2] : false);
+ },
+ setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) {
+ set(this, 8, byteOffset, packFloat64, value, arguments.length > 2 ? arguments[2] : false);
+ }
+ });
+} else {
+ var INCORRECT_ARRAY_BUFFER_NAME = PROPER_FUNCTION_NAME && NativeArrayBuffer.name !== ARRAY_BUFFER;
+ /* eslint-disable no-new, sonarjs/inconsistent-function-call -- required for testing */
+ if (!fails(function () {
+ NativeArrayBuffer(1);
+ }) || !fails(function () {
+ new NativeArrayBuffer(-1);
+ }) || fails(function () {
+ new NativeArrayBuffer();
+ new NativeArrayBuffer(1.5);
+ new NativeArrayBuffer(NaN);
+ return NativeArrayBuffer.length !== 1 || INCORRECT_ARRAY_BUFFER_NAME && !CONFIGURABLE_FUNCTION_NAME;
+ })) {
+ /* eslint-enable no-new, sonarjs/inconsistent-function-call -- required for testing */
+ $ArrayBuffer = function ArrayBuffer(length) {
+ anInstance(this, ArrayBufferPrototype);
+ return inheritIfRequired(new NativeArrayBuffer(toIndex(length)), this, $ArrayBuffer);
+ };
-// `IsConstructor` abstract operation
-// https://tc39.es/ecma262/#sec-isconstructor
-module.exports = !construct || fails(function () {
- var called;
- return isConstructorModern(isConstructorModern.call)
- || !isConstructorModern(Object)
- || !isConstructorModern(function () { called = true; })
- || called;
-}) ? isConstructorLegacy : isConstructorModern;
+ $ArrayBuffer[PROTOTYPE] = ArrayBufferPrototype;
+ ArrayBufferPrototype.constructor = $ArrayBuffer;
-/***/ }),
-/* 104 */
-/***/ (function(module, exports, __webpack_require__) {
+ copyConstructorProperties($ArrayBuffer, NativeArrayBuffer);
+ } else if (INCORRECT_ARRAY_BUFFER_NAME && CONFIGURABLE_FUNCTION_NAME) {
+ createNonEnumerableProperty(NativeArrayBuffer, 'name', ARRAY_BUFFER);
+ }
-"use strict";
+ // WebKit bug - the same parent prototype for typed arrays and data view
+ if (setPrototypeOf && getPrototypeOf(DataViewPrototype) !== ObjectPrototype) {
+ setPrototypeOf(DataViewPrototype, ObjectPrototype);
+ }
-var getBuiltIn = __webpack_require__(43);
-var isCallable = __webpack_require__(46);
-var isPrototypeOf = __webpack_require__(68);
-var USE_SYMBOL_AS_UID = __webpack_require__(278);
+ // iOS Safari 7.x bug
+ var testView = new $DataView(new $ArrayBuffer(2));
+ var $setInt8 = uncurryThis(DataViewPrototype.setInt8);
+ testView.setInt8(0, 2147483648);
+ testView.setInt8(1, 2147483649);
+ if (testView.getInt8(0) || !testView.getInt8(1)) defineBuiltIns(DataViewPrototype, {
+ setInt8: function setInt8(byteOffset, value) {
+ $setInt8(this, byteOffset, value << 24 >> 24);
+ },
+ setUint8: function setUint8(byteOffset, value) {
+ $setInt8(this, byteOffset, value << 24 >> 24);
+ }
+ }, { unsafe: true });
+}
-var $Object = Object;
+setToStringTag($ArrayBuffer, ARRAY_BUFFER);
+setToStringTag($DataView, DATA_VIEW);
-module.exports = USE_SYMBOL_AS_UID ? function (it) {
- return typeof it == 'symbol';
-} : function (it) {
- var $Symbol = getBuiltIn('Symbol');
- return isCallable($Symbol) && isPrototypeOf($Symbol.prototype, $Object(it));
+module.exports = {
+ ArrayBuffer: $ArrayBuffer,
+ DataView: $DataView
};
/***/ }),
-/* 105 */
+/* 112 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var call = __webpack_require__(36);
+var lengthOfArrayLike = __webpack_require__(18);
-module.exports = function (record, fn, ITERATOR_INSTEAD_OF_RECORD) {
- var iterator = ITERATOR_INSTEAD_OF_RECORD ? record : record.iterator;
- var next = record.next;
- var step, result;
- while (!(step = call(next, iterator)).done) {
- result = fn(step.value);
- if (result !== undefined) return result;
- }
+module.exports = function (Constructor, list, $length) {
+ var index = 0;
+ var length = arguments.length > 2 ? $length : lengthOfArrayLike(list);
+ var result = new Constructor(length);
+ while (length > index) result[index] = list[index++];
+ return result;
};
/***/ }),
-/* 106 */
+/* 113 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var internalObjectKeys = __webpack_require__(260);
-var enumBugKeys = __webpack_require__(182);
+var bind = __webpack_require__(43);
+var IndexedObject = __webpack_require__(84);
+var toObject = __webpack_require__(15);
+var lengthOfArrayLike = __webpack_require__(18);
-var hiddenKeys = enumBugKeys.concat('length', 'prototype');
+// `Array.prototype.{ findLast, findLastIndex }` methods implementation
+var createMethod = function (TYPE) {
+ var IS_FIND_LAST_INDEX = TYPE === 1;
+ return function ($this, callbackfn, that) {
+ var O = toObject($this);
+ var self = IndexedObject(O);
+ var index = lengthOfArrayLike(self);
+ var boundFunction = bind(callbackfn, that);
+ var value, result;
+ while (index-- > 0) {
+ value = self[index];
+ result = boundFunction(value, index, O);
+ if (result) switch (TYPE) {
+ case 0: return value; // findLast
+ case 1: return index; // findLastIndex
+ }
+ }
+ return IS_FIND_LAST_INDEX ? -1 : undefined;
+ };
+};
-// `Object.getOwnPropertyNames` method
-// https://tc39.es/ecma262/#sec-object.getownpropertynames
-// eslint-disable-next-line es/no-object-getownpropertynames -- safe
-exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
- return internalObjectKeys(O, hiddenKeys);
+module.exports = {
+ // `Array.prototype.findLast` method
+ // https://github.com/tc39/proposal-array-find-from-last
+ findLast: createMethod(0),
+ // `Array.prototype.findLastIndex` method
+ // https://github.com/tc39/proposal-array-find-from-last
+ findLastIndex: createMethod(1)
};
/***/ }),
-/* 107 */
+/* 114 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var call = __webpack_require__(36);
-var hasOwn = __webpack_require__(45);
-var isPrototypeOf = __webpack_require__(68);
-var regExpFlagsDetection = __webpack_require__(266);
-var regExpFlagsGetterImplementation = __webpack_require__(199);
+var aCallable = __webpack_require__(10);
+var toObject = __webpack_require__(15);
+var IndexedObject = __webpack_require__(84);
+var lengthOfArrayLike = __webpack_require__(18);
-var RegExpPrototype = RegExp.prototype;
+var $TypeError = TypeError;
-module.exports = regExpFlagsDetection.correct ? function (it) {
- return it.flags;
-} : function (it) {
- return (!regExpFlagsDetection.correct && isPrototypeOf(RegExpPrototype, it) && !hasOwn(it, 'flags'))
- ? call(regExpFlagsGetterImplementation, it)
- : it.flags;
+var REDUCE_EMPTY = 'Reduce of empty array with no initial value';
+
+// `Array.prototype.{ reduce, reduceRight }` methods implementation
+var createMethod = function (IS_RIGHT) {
+ return function (that, callbackfn, argumentsLength, memo) {
+ var O = toObject(that);
+ var self = IndexedObject(O);
+ var length = lengthOfArrayLike(O);
+ aCallable(callbackfn);
+ if (length === 0 && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);
+ var index = IS_RIGHT ? length - 1 : 0;
+ var i = IS_RIGHT ? -1 : 1;
+ if (argumentsLength < 2) while (true) {
+ if (index in self) {
+ memo = self[index];
+ index += i;
+ break;
+ }
+ index += i;
+ if (IS_RIGHT ? index < 0 : length <= index) {
+ throw new $TypeError(REDUCE_EMPTY);
+ }
+ }
+ for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {
+ memo = callbackfn(memo, self[index], index, O);
+ }
+ return memo;
+ };
+};
+
+module.exports = {
+ // `Array.prototype.reduce` method
+ // https://tc39.es/ecma262/#sec-array.prototype.reduce
+ left: createMethod(false),
+ // `Array.prototype.reduceRight` method
+ // https://tc39.es/ecma262/#sec-array.prototype.reduceright
+ right: createMethod(true)
};
/***/ }),
-/* 108 */
+/* 115 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var getBuiltIn = __webpack_require__(43);
+var wellKnownSymbol = __webpack_require__(7);
-var createSetLike = function (size) {
- return {
- size: size,
- has: function () {
- return false;
- },
- keys: function () {
- return {
- next: function () {
- return { done: true };
- }
- };
- }
- };
-};
+var ITERATOR = wellKnownSymbol('iterator');
+var SAFE_CLOSING = false;
-var createSetLikeWithInfinitySize = function (size) {
- return {
- size: size,
- has: function () {
- return true;
+try {
+ var called = 0;
+ var iteratorWithReturn = {
+ next: function () {
+ return { done: !!called++ };
},
- keys: function () {
- throw new Error('e');
+ 'return': function () {
+ SAFE_CLOSING = true;
}
};
-};
+ iteratorWithReturn[ITERATOR] = function () {
+ return this;
+ };
+ // eslint-disable-next-line es/no-array-from, no-throw-literal -- required for testing
+ Array.from(iteratorWithReturn, function () { throw 2; });
+} catch (error) { /* empty */ }
-module.exports = function (name, callback) {
- var Set = getBuiltIn('Set');
+module.exports = function (exec, SKIP_CLOSING) {
try {
- new Set()[name](createSetLike(0));
- try {
- // late spec change, early WebKit ~ Safari 17 implementation does not pass it
- // https://github.com/tc39/proposal-set-methods/pull/88
- // also covered engines with
- // https://bugs.webkit.org/show_bug.cgi?id=272679
- new Set()[name](createSetLike(-1));
- return false;
- } catch (error2) {
- if (!callback) return true;
- // early V8 implementation bug
- // https://issues.chromium.org/issues/351332634
- try {
- new Set()[name](createSetLikeWithInfinitySize(-Infinity));
- return false;
- } catch (error) {
- var set = new Set();
- set.add(1);
- set.add(2);
- return callback(set[name](createSetLikeWithInfinitySize(Infinity)));
- }
- }
- } catch (error) {
- return false;
- }
+ if (!SKIP_CLOSING && !SAFE_CLOSING) return false;
+ } catch (error) { return false; } // workaround of old WebKit + `eval` bug
+ var ITERATION_SUPPORT = false;
+ try {
+ var object = {};
+ object[ITERATOR] = function () {
+ return {
+ next: function () {
+ return { done: ITERATION_SUPPORT = true };
+ }
+ };
+ };
+ exec(object);
+ } catch (error) { /* empty */ }
+ return ITERATION_SUPPORT;
};
/***/ }),
-/* 109 */
+/* 116 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var $String = String;
+var $ = __webpack_require__(0);
+var globalThis = __webpack_require__(3);
+var uncurryThis = __webpack_require__(2);
+var isForced = __webpack_require__(101);
+var defineBuiltIn = __webpack_require__(17);
+var InternalMetadataModule = __webpack_require__(71);
+var iterate = __webpack_require__(24);
+var anInstance = __webpack_require__(39);
+var isCallable = __webpack_require__(14);
+var isNullOrUndefined = __webpack_require__(57);
+var isObject = __webpack_require__(8);
+var fails = __webpack_require__(1);
+var checkCorrectnessOfIteration = __webpack_require__(115);
+var setToStringTag = __webpack_require__(38);
+var inheritIfRequired = __webpack_require__(70);
-module.exports = function (argument) {
- try {
- return $String(argument);
- } catch (error) {
- return 'Object';
- }
-};
+module.exports = function (CONSTRUCTOR_NAME, wrapper, common) {
+ var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;
+ var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;
+ var ADDER = IS_MAP ? 'set' : 'add';
+ var NativeConstructor = globalThis[CONSTRUCTOR_NAME];
+ var NativePrototype = NativeConstructor && NativeConstructor.prototype;
+ var Constructor = NativeConstructor;
+ var exported = {};
+ var fixMethod = function (KEY) {
+ var uncurriedNativeMethod = uncurryThis(NativePrototype[KEY]);
+ defineBuiltIn(NativePrototype, KEY,
+ KEY === 'add' ? function add(value) {
+ uncurriedNativeMethod(this, value === 0 ? 0 : value);
+ return this;
+ } : KEY === 'delete' ? function (key) {
+ return IS_WEAK && !isObject(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
+ } : KEY === 'get' ? function get(key) {
+ return IS_WEAK && !isObject(key) ? undefined : uncurriedNativeMethod(this, key === 0 ? 0 : key);
+ } : KEY === 'has' ? function has(key) {
+ return IS_WEAK && !isObject(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
+ } : function set(key, value) {
+ uncurriedNativeMethod(this, key === 0 ? 0 : key, value);
+ return this;
+ }
+ );
+ };
-/***/ }),
-/* 110 */
-/***/ (function(module, exports, __webpack_require__) {
+ var REPLACE = isForced(
+ CONSTRUCTOR_NAME,
+ !isCallable(NativeConstructor) || !(IS_WEAK || NativePrototype.forEach && !fails(function () {
+ new NativeConstructor().entries().next();
+ }))
+ );
-"use strict";
+ if (REPLACE) {
+ // create collection constructor
+ Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER);
+ InternalMetadataModule.enable();
+ } else if (isForced(CONSTRUCTOR_NAME, true)) {
+ var instance = new Constructor();
+ // early implementations not supports chaining
+ var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) !== instance;
+ // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false
+ var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });
+ // most early implementations doesn't supports iterables, most modern - not close it correctly
+ // eslint-disable-next-line no-new -- required for testing
+ var ACCEPT_ITERABLES = checkCorrectnessOfIteration(function (iterable) { new NativeConstructor(iterable); });
+ // for early implementations -0 and +0 not the same
+ var BUGGY_ZERO = !IS_WEAK && fails(function () {
+ // V8 ~ Chromium 42- fails only with 5+ elements
+ var $instance = new NativeConstructor();
+ var index = 5;
+ while (index--) $instance[ADDER](index, index);
+ return !$instance.has(-0);
+ });
-var hasOwn = __webpack_require__(45);
-var ownKeys = __webpack_require__(197);
-var getOwnPropertyDescriptorModule = __webpack_require__(63);
-var definePropertyModule = __webpack_require__(51);
+ if (!ACCEPT_ITERABLES) {
+ Constructor = wrapper(function (dummy, iterable) {
+ anInstance(dummy, NativePrototype);
+ var that = inheritIfRequired(new NativeConstructor(), dummy, Constructor);
+ if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
+ return that;
+ });
+ Constructor.prototype = NativePrototype;
+ NativePrototype.constructor = Constructor;
+ }
-module.exports = function (target, source, exceptions) {
- var keys = ownKeys(source);
- var defineProperty = definePropertyModule.f;
- var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule.f;
- for (var i = 0; i < keys.length; i++) {
- var key = keys[i];
- if (!hasOwn(target, key) && !(exceptions && hasOwn(exceptions, key))) {
- defineProperty(target, key, getOwnPropertyDescriptor(source, key));
+ if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
+ fixMethod('delete');
+ fixMethod('has');
+ IS_MAP && fixMethod('get');
}
+
+ if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
+
+ // weak collections should not contains .clear method
+ if (IS_WEAK && NativePrototype.clear) delete NativePrototype.clear;
}
+
+ exported[CONSTRUCTOR_NAME] = Constructor;
+ $({ global: true, constructor: true, forced: Constructor !== NativeConstructor }, exported);
+
+ setToStringTag(Constructor, CONSTRUCTOR_NAME);
+
+ if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP);
+
+ return Constructor;
};
/***/ }),
-/* 111 */
+/* 117 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var ENVIRONMENT = __webpack_require__(149);
+var tryToString = __webpack_require__(78);
-module.exports = ENVIRONMENT === 'NODE';
+var $TypeError = TypeError;
+
+module.exports = function (O, P) {
+ if (!delete O[P]) throw new $TypeError('Cannot delete property ' + tryToString(P) + ' of ' + tryToString(O));
+};
/***/ }),
-/* 112 */
+/* 118 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var fails = __webpack_require__(33);
+var globalThis = __webpack_require__(3);
+var isObject = __webpack_require__(8);
-module.exports = !fails(function () {
- // eslint-disable-next-line es/no-object-isextensible, es/no-object-preventextensions -- required for testing
- return Object.isExtensible(Object.preventExtensions({}));
-});
+var document = globalThis.document;
+// typeof document.createElement is 'object' in old IE
+var EXISTS = isObject(document) && isObject(document.createElement);
+
+module.exports = function (it) {
+ return EXISTS ? document.createElement(it) : {};
+};
/***/ }),
-/* 113 */
+/* 119 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var DESCRIPTORS = __webpack_require__(38);
-var hasOwn = __webpack_require__(45);
-
-var FunctionPrototype = Function.prototype;
-// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
-var getDescriptor = DESCRIPTORS && Object.getOwnPropertyDescriptor;
-
-var EXISTS = hasOwn(FunctionPrototype, 'name');
-// additional protection from minified / mangled / dropped function names
-var PROPER = EXISTS && (function something() { /* empty */ }).name === 'something';
-var CONFIGURABLE = EXISTS && (!DESCRIPTORS || (DESCRIPTORS && getDescriptor(FunctionPrototype, 'name').configurable));
+/* global Bun, Deno -- detection */
+var globalThis = __webpack_require__(3);
+var userAgent = __webpack_require__(51);
+var classof = __webpack_require__(32);
-module.exports = {
- EXISTS: EXISTS,
- PROPER: PROPER,
- CONFIGURABLE: CONFIGURABLE
+var userAgentStartsWith = function (string) {
+ return userAgent.slice(0, string.length) === string;
};
+module.exports = (function () {
+ if (userAgentStartsWith('Bun/')) return 'BUN';
+ if (userAgentStartsWith('Cloudflare-Workers')) return 'CLOUDFLARE';
+ if (userAgentStartsWith('Deno/')) return 'DENO';
+ if (userAgentStartsWith('Node.js/')) return 'NODE';
+ if (globalThis.Bun && typeof Bun.version == 'string') return 'BUN';
+ if (globalThis.Deno && typeof Deno.version == 'object') return 'DENO';
+ if (classof(globalThis.process) === 'process') return 'NODE';
+ if (globalThis.window && globalThis.document) return 'BROWSER';
+ return 'REST';
+})();
+
/***/ }),
-/* 114 */
+/* 120 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var call = __webpack_require__(36);
-var aCallable = __webpack_require__(42);
-var anObject = __webpack_require__(37);
-var tryToString = __webpack_require__(109);
-var getIteratorMethod = __webpack_require__(99);
+// TODO: Remove from `core-js@4` since it's moved to entry points
+__webpack_require__(180);
+var call = __webpack_require__(4);
+var defineBuiltIn = __webpack_require__(17);
+var regexpExec = __webpack_require__(169);
+var fails = __webpack_require__(1);
+var wellKnownSymbol = __webpack_require__(7);
+var createNonEnumerableProperty = __webpack_require__(27);
-var $TypeError = TypeError;
+var SPECIES = wellKnownSymbol('species');
+var RegExpPrototype = RegExp.prototype;
-module.exports = function (argument, usingIterator) {
- var iteratorMethod = arguments.length < 2 ? getIteratorMethod(argument) : usingIterator;
- if (aCallable(iteratorMethod)) return anObject(call(iteratorMethod, argument));
- throw new $TypeError(tryToString(argument) + ' is not iterable');
+module.exports = function (KEY, exec, FORCED, SHAM) {
+ var SYMBOL = wellKnownSymbol(KEY);
+
+ var DELEGATES_TO_SYMBOL = !fails(function () {
+ // String methods call symbol-named RegExp methods
+ var O = {};
+ O[SYMBOL] = function () { return 7; };
+ return ''[KEY](O) !== 7;
+ });
+
+ var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails(function () {
+ // Symbol-named RegExp methods call .exec
+ var execCalled = false;
+ var re = /a/;
+
+ if (KEY === 'split') {
+ // We can't use real regex here since it causes deoptimization
+ // and serious performance degradation in V8
+ // https://github.com/zloirock/core-js/issues/306
+ re = {};
+ // RegExp[@@split] doesn't call the regex's exec method, but first creates
+ // a new one. We need to return the patched regex when creating the new one.
+ re.constructor = {};
+ re.constructor[SPECIES] = function () { return re; };
+ re.flags = '';
+ re[SYMBOL] = /./[SYMBOL];
+ }
+
+ re.exec = function () {
+ execCalled = true;
+ return null;
+ };
+
+ re[SYMBOL]('');
+ return !execCalled;
+ });
+
+ if (
+ !DELEGATES_TO_SYMBOL ||
+ !DELEGATES_TO_EXEC ||
+ FORCED
+ ) {
+ var nativeRegExpMethod = /./[SYMBOL];
+ var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) {
+ var $exec = regexp.exec;
+ if ($exec === regexpExec || $exec === RegExpPrototype.exec) {
+ if (DELEGATES_TO_SYMBOL && !forceStringMethod) {
+ // The native String method already delegates to @@method (this
+ // polyfilled function), leasing to infinite recursion.
+ // We avoid it by directly calling the native @@method method.
+ return { done: true, value: call(nativeRegExpMethod, regexp, str, arg2) };
+ }
+ return { done: true, value: call(nativeMethod, str, regexp, arg2) };
+ }
+ return { done: false };
+ });
+
+ defineBuiltIn(String.prototype, KEY, methods[0]);
+ defineBuiltIn(RegExpPrototype, SYMBOL, methods[1]);
+ }
+
+ if (SHAM) createNonEnumerableProperty(RegExpPrototype[SYMBOL], 'sham', true);
};
/***/ }),
-/* 115 */
+/* 121 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
-var fails = __webpack_require__(33);
-var classof = __webpack_require__(64);
+var uncurryThis = __webpack_require__(2);
+var aCallable = __webpack_require__(10);
-var $Object = Object;
-var split = uncurryThis(''.split);
-
-// fallback for non-array-like ES3 and non-enumerable old V8 strings
-module.exports = fails(function () {
- // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
- // eslint-disable-next-line no-prototype-builtins -- safe
- return !$Object('z').propertyIsEnumerable(0);
-}) ? function (it) {
- return classof(it) === 'String' ? split(it, '') : $Object(it);
-} : $Object;
+module.exports = function (object, key, method) {
+ try {
+ // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+ return uncurryThis(aCallable(Object.getOwnPropertyDescriptor(object, key)[method]));
+ } catch (error) { /* empty */ }
+};
/***/ }),
-/* 116 */
+/* 122 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var call = __webpack_require__(36);
-var create = __webpack_require__(62);
-var createNonEnumerableProperty = __webpack_require__(59);
-var defineBuiltIns = __webpack_require__(88);
-var wellKnownSymbol = __webpack_require__(39);
-var InternalStateModule = __webpack_require__(53);
-var getMethod = __webpack_require__(60);
-var IteratorPrototype = __webpack_require__(117).IteratorPrototype;
-var createIterResultObject = __webpack_require__(96);
-var iteratorClose = __webpack_require__(61);
-var iteratorCloseAll = __webpack_require__(302);
-
-var TO_STRING_TAG = wellKnownSymbol('toStringTag');
-var ITERATOR_HELPER = 'IteratorHelper';
-var WRAP_FOR_VALID_ITERATOR = 'WrapForValidIterator';
-var NORMAL = 'normal';
-var THROW = 'throw';
-var setInternalState = InternalStateModule.set;
+var isObject = __webpack_require__(8);
+var classof = __webpack_require__(32);
+var wellKnownSymbol = __webpack_require__(7);
-var createIteratorProxyPrototype = function (IS_ITERATOR) {
- var getInternalState = InternalStateModule.getterFor(IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER);
+var MATCH = wellKnownSymbol('match');
- return defineBuiltIns(create(IteratorPrototype), {
- next: function next() {
- var state = getInternalState(this);
- // for simplification:
- // for `%WrapForValidIteratorPrototype%.next` or with `state.returnHandlerResult` our `nextHandler` returns `IterResultObject`
- // for `%IteratorHelperPrototype%.next` - just a value
- if (IS_ITERATOR) return state.nextHandler();
- if (state.done) return createIterResultObject(undefined, true);
- try {
- var result = state.nextHandler();
- return state.returnHandlerResult ? result : createIterResultObject(result, state.done);
- } catch (error) {
- state.done = true;
- throw error;
- }
- },
- 'return': function () {
- var state = getInternalState(this);
- var iterator = state.iterator;
- state.done = true;
- if (IS_ITERATOR) {
- var returnMethod = getMethod(iterator, 'return');
- return returnMethod ? call(returnMethod, iterator) : createIterResultObject(undefined, true);
- }
- if (state.inner) try {
- iteratorClose(state.inner.iterator, NORMAL);
- } catch (error) {
- return iteratorClose(iterator, THROW, error);
- }
- if (state.openIters) try {
- iteratorCloseAll(state.openIters, NORMAL);
- } catch (error) {
- return iteratorClose(iterator, THROW, error);
- }
- if (iterator) iteratorClose(iterator, NORMAL);
- return createIterResultObject(undefined, true);
- }
- });
+// `IsRegExp` abstract operation
+// https://tc39.es/ecma262/#sec-isregexp
+module.exports = function (it) {
+ var isRegExp;
+ return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : classof(it) === 'RegExp');
};
-var WrapForValidIteratorPrototype = createIteratorProxyPrototype(true);
-var IteratorHelperPrototype = createIteratorProxyPrototype(false);
-
-createNonEnumerableProperty(IteratorHelperPrototype, TO_STRING_TAG, 'Iterator Helper');
-module.exports = function (nextHandler, IS_ITERATOR, RETURN_HANDLER_RESULT) {
- var IteratorProxy = function Iterator(record, state) {
- if (state) {
- state.iterator = record.iterator;
- state.next = record.next;
- } else state = record;
- state.type = IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER;
- state.returnHandlerResult = !!RETURN_HANDLER_RESULT;
- state.nextHandler = nextHandler;
- state.counter = 0;
- state.done = false;
- setInternalState(this, state);
- };
+/***/ }),
+/* 123 */
+/***/ (function(module, exports, __webpack_require__) {
- IteratorProxy.prototype = IS_ITERATOR ? WrapForValidIteratorPrototype : IteratorHelperPrototype;
+"use strict";
- return IteratorProxy;
+// Should throw an error on invalid iterator
+// https://issues.chromium.org/issues/336839115
+module.exports = function (methodName, argument) {
+ // eslint-disable-next-line es/no-iterator -- required for testing
+ var method = typeof Iterator == 'function' && Iterator.prototype[methodName];
+ if (method) try {
+ method.call({ next: null }, argument).next();
+ } catch (error) {
+ return true;
+ }
};
/***/ }),
-/* 117 */
+/* 124 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var fails = __webpack_require__(33);
-var isCallable = __webpack_require__(46);
-var isObject = __webpack_require__(40);
-var create = __webpack_require__(62);
-var getPrototypeOf = __webpack_require__(67);
-var defineBuiltIn = __webpack_require__(49);
-var wellKnownSymbol = __webpack_require__(39);
-var IS_PURE = __webpack_require__(48);
-
-var ITERATOR = wellKnownSymbol('iterator');
-var BUGGY_SAFARI_ITERATORS = false;
-
-// `%IteratorPrototype%` object
-// https://tc39.es/ecma262/#sec-%iteratorprototype%-object
-var IteratorPrototype, PrototypeOfArrayIteratorPrototype, arrayIterator;
+// eslint-disable-next-line es/no-math-expm1 -- safe
+var $expm1 = Math.expm1;
+var exp = Math.exp;
-/* eslint-disable es/no-array-prototype-keys -- safe */
-if ([].keys) {
- arrayIterator = [].keys();
- // Safari 8 has buggy iterators w/o `next`
- if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS = true;
- else {
- PrototypeOfArrayIteratorPrototype = getPrototypeOf(getPrototypeOf(arrayIterator));
- if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype = PrototypeOfArrayIteratorPrototype;
- }
-}
+// `Math.expm1` method implementation
+// https://tc39.es/ecma262/#sec-math.expm1
+module.exports = (!$expm1
+ // Old FF bug
+ // eslint-disable-next-line no-loss-of-precision -- required for old engines
+ || $expm1(10) > 22025.465794806719 || $expm1(10) < 22025.4657948067165168
+ // Tor Browser bug
+ || $expm1(-2e-17) !== -2e-17
+) ? function expm1(x) {
+ var n = +x;
+ return n === 0 ? n : n > -1e-6 && n < 1e-6 ? n + n * n / 2 : exp(n) - 1;
+} : $expm1;
-var NEW_ITERATOR_PROTOTYPE = !isObject(IteratorPrototype) || fails(function () {
- var test = {};
- // FF44- legacy iterators case
- return IteratorPrototype[ITERATOR].call(test) !== test;
-});
-if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype = {};
-else if (IS_PURE) IteratorPrototype = create(IteratorPrototype);
+/***/ }),
+/* 125 */
+/***/ (function(module, exports, __webpack_require__) {
-// `%IteratorPrototype%[@@iterator]()` method
-// https://tc39.es/ecma262/#sec-%iteratorprototype%-@@iterator
-if (!isCallable(IteratorPrototype[ITERATOR])) {
- defineBuiltIn(IteratorPrototype, ITERATOR, function () {
- return this;
- });
-}
+"use strict";
-module.exports = {
- IteratorPrototype: IteratorPrototype,
- BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS
-};
+// eslint-disable-next-line es/no-object-getownpropertysymbols -- safe
+exports.f = Object.getOwnPropertySymbols;
/***/ }),
-/* 118 */
+/* 126 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var toString = __webpack_require__(41);
+var $propertyIsEnumerable = {}.propertyIsEnumerable;
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
+// Nashorn ~ JDK8 bug
+var NASHORN_BUG = getOwnPropertyDescriptor && !$propertyIsEnumerable.call({ 1: 2 }, 1);
-module.exports = function (argument, $default) {
- return argument === undefined ? arguments.length < 2 ? '' : $default : toString(argument);
-};
+// `Object.prototype.propertyIsEnumerable` method implementation
+// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
+exports.f = NASHORN_BUG ? function propertyIsEnumerable(V) {
+ var descriptor = getOwnPropertyDescriptor(this, V);
+ return !!descriptor && descriptor.enumerable;
+} : $propertyIsEnumerable;
/***/ }),
-/* 119 */
+/* 127 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-module.exports = function (exec) {
- try {
- return { error: false, value: exec() };
- } catch (error) {
- return { error: true, value: error };
- }
-};
+/* eslint-disable no-undef, no-useless-call, sonarjs/no-reference-error -- required for testing */
+/* eslint-disable es/no-legacy-object-prototype-accessor-methods -- required for testing */
+var IS_PURE = __webpack_require__(16);
+var globalThis = __webpack_require__(3);
+var fails = __webpack_require__(1);
+var WEBKIT = __webpack_require__(154);
+
+// Forced replacement object prototype accessors methods
+module.exports = IS_PURE || !fails(function () {
+ // This feature detection crashes old WebKit
+ // https://github.com/zloirock/core-js/issues/232
+ if (WEBKIT && WEBKIT < 535) return;
+ var key = Math.random();
+ // In FF throws only define methods
+ __defineSetter__.call(null, key, function () { /* empty */ });
+ delete globalThis[key];
+});
/***/ }),
-/* 120 */
+/* 128 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
+var globalThis = __webpack_require__(3);
-module.exports = globalThis.Promise;
+module.exports = globalThis;
/***/ }),
-/* 121 */
+/* 129 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
-var iterateSimple = __webpack_require__(105);
-var SetHelpers = __webpack_require__(82);
+var NativePromiseConstructor = __webpack_require__(89);
+var checkCorrectnessOfIteration = __webpack_require__(115);
+var FORCED_PROMISE_CONSTRUCTOR = __webpack_require__(104).CONSTRUCTOR;
-var Set = SetHelpers.Set;
-var SetPrototype = SetHelpers.proto;
-var forEach = uncurryThis(SetPrototype.forEach);
-var keys = uncurryThis(SetPrototype.keys);
-var next = keys(new Set()).next;
-
-module.exports = function (set, fn, interruptible) {
- return interruptible ? iterateSimple({ iterator: keys(set), next: next }, fn) : forEach(set, fn);
-};
+module.exports = FORCED_PROMISE_CONSTRUCTOR || !checkCorrectnessOfIteration(function (iterable) {
+ NativePromiseConstructor.all(iterable).then(undefined, function () { /* empty */ });
+});
/***/ }),
-/* 122 */
+/* 130 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var getBuiltIn = __webpack_require__(43);
-var defineBuiltInAccessor = __webpack_require__(55);
-var wellKnownSymbol = __webpack_require__(39);
-var DESCRIPTORS = __webpack_require__(38);
+var fails = __webpack_require__(1);
+var globalThis = __webpack_require__(3);
-var SPECIES = wellKnownSymbol('species');
+// babel-minify and Closure Compiler transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError
+var $RegExp = globalThis.RegExp;
-module.exports = function (CONSTRUCTOR_NAME) {
- var Constructor = getBuiltIn(CONSTRUCTOR_NAME);
+var UNSUPPORTED_Y = fails(function () {
+ var re = $RegExp('a', 'y');
+ re.lastIndex = 2;
+ return re.exec('abcd') !== null;
+});
- if (DESCRIPTORS && Constructor && !Constructor[SPECIES]) {
- defineBuiltInAccessor(Constructor, SPECIES, {
- configurable: true,
- get: function () { return this; }
- });
- }
+// UC Browser bug
+// https://github.com/zloirock/core-js/issues/1008
+var MISSED_STICKY = UNSUPPORTED_Y || fails(function () {
+ return !$RegExp('a', 'y').sticky;
+});
+
+var BROKEN_CARET = UNSUPPORTED_Y || fails(function () {
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=773687
+ var re = $RegExp('^r', 'gy');
+ re.lastIndex = 2;
+ return re.exec('str') !== null;
+});
+
+module.exports = {
+ BROKEN_CARET: BROKEN_CARET,
+ MISSED_STICKY: MISSED_STICKY,
+ UNSUPPORTED_Y: UNSUPPORTED_Y
};
/***/ }),
-/* 123 */
+/* 131 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var store = __webpack_require__(162);
+var shared = __webpack_require__(92);
+var uid = __webpack_require__(95);
-module.exports = function (key, value) {
- return store[key] || (store[key] = value || {});
+var keys = shared('keys');
+
+module.exports = function (key) {
+ return keys[key] || (keys[key] = uid(key));
};
/***/ }),
-/* 124 */
+/* 132 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
-var requireObjectCoercible = __webpack_require__(52);
-var toString = __webpack_require__(41);
-var whitespaces = __webpack_require__(138);
-
-var replace = uncurryThis(''.replace);
-var ltrim = RegExp('^[' + whitespaces + ']+');
-var rtrim = RegExp('(^|[^' + whitespaces + '])[' + whitespaces + ']+$');
+var IS_PURE = __webpack_require__(16);
+var globalThis = __webpack_require__(3);
+var defineGlobalProperty = __webpack_require__(152);
-// `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation
-var createMethod = function (TYPE) {
- return function ($this) {
- var string = toString(requireObjectCoercible($this));
- if (TYPE & 1) string = replace(string, ltrim, '');
- if (TYPE & 2) string = replace(string, rtrim, '$1');
- return string;
- };
-};
+var SHARED = '__core-js_shared__';
+var store = module.exports = globalThis[SHARED] || defineGlobalProperty(SHARED, {});
-module.exports = {
- // `String.prototype.{ trimLeft, trimStart }` methods
- // https://tc39.es/ecma262/#sec-string.prototype.trimstart
- start: createMethod(1),
- // `String.prototype.{ trimRight, trimEnd }` methods
- // https://tc39.es/ecma262/#sec-string.prototype.trimend
- end: createMethod(2),
- // `String.prototype.trim` method
- // https://tc39.es/ecma262/#sec-string.prototype.trim
- trim: createMethod(3)
-};
+(store.versions || (store.versions = [])).push({
+ version: '3.43.0',
+ mode: IS_PURE ? 'pure' : 'global',
+ copyright: '© 2014-2025 Denis Pushkarev (zloirock.ru)',
+ license: 'https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE',
+ source: 'https://github.com/zloirock/core-js'
+});
/***/ }),
-/* 125 */
+/* 133 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-/* eslint-disable es/no-symbol -- required for testing */
-var V8_VERSION = __webpack_require__(84);
-var fails = __webpack_require__(33);
-var globalThis = __webpack_require__(35);
+var anObject = __webpack_require__(5);
+var aConstructor = __webpack_require__(144);
+var isNullOrUndefined = __webpack_require__(57);
+var wellKnownSymbol = __webpack_require__(7);
-var $String = globalThis.String;
+var SPECIES = wellKnownSymbol('species');
-// eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing
-module.exports = !!Object.getOwnPropertySymbols && !fails(function () {
- var symbol = Symbol('symbol detection');
- // Chrome 38 Symbol has incorrect toString conversion
- // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
- // nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
- // of course, fail.
- return !$String(symbol) || !(Object(symbol) instanceof Symbol) ||
- // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
- !Symbol.sham && V8_VERSION && V8_VERSION < 41;
-});
+// `SpeciesConstructor` abstract operation
+// https://tc39.es/ecma262/#sec-speciesconstructor
+module.exports = function (O, defaultConstructor) {
+ var C = anObject(O).constructor;
+ var S;
+ return C === undefined || isNullOrUndefined(S = anObject(C)[SPECIES]) ? defaultConstructor : aConstructor(S);
+};
/***/ }),
-/* 126 */
+/* 134 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
+var uncurryThis = __webpack_require__(2);
+var toIntegerOrInfinity = __webpack_require__(22);
+var toString = __webpack_require__(9);
+var requireObjectCoercible = __webpack_require__(20);
-var id = 0;
-var postfix = Math.random();
-var toString = uncurryThis(1.1.toString);
+var charAt = uncurryThis(''.charAt);
+var charCodeAt = uncurryThis(''.charCodeAt);
+var stringSlice = uncurryThis(''.slice);
-module.exports = function (key) {
- return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString(++id + postfix, 36);
+var createMethod = function (CONVERT_TO_STRING) {
+ return function ($this, pos) {
+ var S = toString(requireObjectCoercible($this));
+ var position = toIntegerOrInfinity(pos);
+ var size = S.length;
+ var first, second;
+ if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
+ first = charCodeAt(S, position);
+ return first < 0xD800 || first > 0xDBFF || position + 1 === size
+ || (second = charCodeAt(S, position + 1)) < 0xDC00 || second > 0xDFFF
+ ? CONVERT_TO_STRING
+ ? charAt(S, position)
+ : first
+ : CONVERT_TO_STRING
+ ? stringSlice(S, position, position + 2)
+ : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
+ };
+};
+
+module.exports = {
+ // `String.prototype.codePointAt` method
+ // https://tc39.es/ecma262/#sec-string.prototype.codepointat
+ codeAt: createMethod(false),
+ // `String.prototype.at` method
+ // https://github.com/mathiasbynens/String.prototype.at
+ charAt: createMethod(true)
};
/***/ }),
-/* 127 */
+/* 135 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var toIndexedObject = __webpack_require__(57);
-var toAbsoluteIndex = __webpack_require__(91);
-var lengthOfArrayLike = __webpack_require__(50);
+// https://github.com/tc39/proposal-string-pad-start-end
+var uncurryThis = __webpack_require__(2);
+var toLength = __webpack_require__(45);
+var toString = __webpack_require__(9);
+var $repeat = __webpack_require__(136);
+var requireObjectCoercible = __webpack_require__(20);
-// `Array.prototype.{ indexOf, includes }` methods implementation
-var createMethod = function (IS_INCLUDES) {
- return function ($this, el, fromIndex) {
- var O = toIndexedObject($this);
- var length = lengthOfArrayLike(O);
- if (length === 0) return !IS_INCLUDES && -1;
- var index = toAbsoluteIndex(fromIndex, length);
- var value;
- // Array#includes uses SameValueZero equality algorithm
- // eslint-disable-next-line no-self-compare -- NaN check
- if (IS_INCLUDES && el !== el) while (length > index) {
- value = O[index++];
- // eslint-disable-next-line no-self-compare -- NaN check
- if (value !== value) return true;
- // Array#indexOf ignores holes, Array#includes - not
- } else for (;length > index; index++) {
- if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
- } return !IS_INCLUDES && -1;
+var repeat = uncurryThis($repeat);
+var stringSlice = uncurryThis(''.slice);
+var ceil = Math.ceil;
+
+// `String.prototype.{ padStart, padEnd }` methods implementation
+var createMethod = function (IS_END) {
+ return function ($this, maxLength, fillString) {
+ var S = toString(requireObjectCoercible($this));
+ var intMaxLength = toLength(maxLength);
+ var stringLength = S.length;
+ var fillStr = fillString === undefined ? ' ' : toString(fillString);
+ var fillLen, stringFiller;
+ if (intMaxLength <= stringLength || fillStr === '') return S;
+ fillLen = intMaxLength - stringLength;
+ stringFiller = repeat(fillStr, ceil(fillLen / fillStr.length));
+ if (stringFiller.length > fillLen) stringFiller = stringSlice(stringFiller, 0, fillLen);
+ return IS_END ? S + stringFiller : stringFiller + S;
};
};
module.exports = {
- // `Array.prototype.includes` method
- // https://tc39.es/ecma262/#sec-array.prototype.includes
- includes: createMethod(true),
- // `Array.prototype.indexOf` method
- // https://tc39.es/ecma262/#sec-array.prototype.indexof
- indexOf: createMethod(false)
+ // `String.prototype.padStart` method
+ // https://tc39.es/ecma262/#sec-string.prototype.padstart
+ start: createMethod(false),
+ // `String.prototype.padEnd` method
+ // https://tc39.es/ecma262/#sec-string.prototype.padend
+ end: createMethod(true)
};
/***/ }),
-/* 128 */
+/* 136 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var fails = __webpack_require__(33);
-var wellKnownSymbol = __webpack_require__(39);
-var V8_VERSION = __webpack_require__(84);
+var toIntegerOrInfinity = __webpack_require__(22);
+var toString = __webpack_require__(9);
+var requireObjectCoercible = __webpack_require__(20);
-var SPECIES = wellKnownSymbol('species');
+var $RangeError = RangeError;
-module.exports = function (METHOD_NAME) {
- // We can't use this feature detection in V8 since it causes
- // deoptimization and serious performance degradation
- // https://github.com/zloirock/core-js/issues/677
- return V8_VERSION >= 51 || !fails(function () {
- var array = [];
- var constructor = array.constructor = {};
- constructor[SPECIES] = function () {
- return { foo: 1 };
- };
- return array[METHOD_NAME](Boolean).foo !== 1;
- });
+// `String.prototype.repeat` method implementation
+// https://tc39.es/ecma262/#sec-string.prototype.repeat
+module.exports = function repeat(count) {
+ var str = toString(requireObjectCoercible(this));
+ var result = '';
+ var n = toIntegerOrInfinity(count);
+ if (n < 0 || n === Infinity) throw new $RangeError('Wrong number of repetitions');
+ for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) result += str;
+ return result;
};
/***/ }),
-/* 129 */
+/* 137 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var arraySpeciesConstructor = __webpack_require__(291);
+var globalThis = __webpack_require__(3);
+var apply = __webpack_require__(42);
+var bind = __webpack_require__(43);
+var isCallable = __webpack_require__(14);
+var hasOwn = __webpack_require__(13);
+var fails = __webpack_require__(1);
+var html = __webpack_require__(212);
+var arraySlice = __webpack_require__(46);
+var createElement = __webpack_require__(118);
+var validateArgumentsLength = __webpack_require__(48);
+var IS_IOS = __webpack_require__(203);
+var IS_NODE = __webpack_require__(80);
-// `ArraySpeciesCreate` abstract operation
-// https://tc39.es/ecma262/#sec-arrayspeciescreate
-module.exports = function (originalArray, length) {
- return new (arraySpeciesConstructor(originalArray))(length === 0 ? 0 : length);
+var set = globalThis.setImmediate;
+var clear = globalThis.clearImmediate;
+var process = globalThis.process;
+var Dispatch = globalThis.Dispatch;
+var Function = globalThis.Function;
+var MessageChannel = globalThis.MessageChannel;
+var String = globalThis.String;
+var counter = 0;
+var queue = {};
+var ONREADYSTATECHANGE = 'onreadystatechange';
+var $location, defer, channel, port;
+
+fails(function () {
+ // Deno throws a ReferenceError on `location` access without `--location` flag
+ $location = globalThis.location;
+});
+
+var run = function (id) {
+ if (hasOwn(queue, id)) {
+ var fn = queue[id];
+ delete queue[id];
+ fn();
+ }
};
+var runner = function (id) {
+ return function () {
+ run(id);
+ };
+};
-/***/ }),
-/* 130 */
-/***/ (function(module, exports, __webpack_require__) {
+var eventListener = function (event) {
+ run(event.data);
+};
-"use strict";
+var globalPostMessageDefer = function (id) {
+ // old engines have not location.origin
+ globalThis.postMessage(String(id), $location.protocol + '//' + $location.host);
+};
-var fails = __webpack_require__(33);
+// Node.js 0.9+ & IE10+ has setImmediate, otherwise:
+if (!set || !clear) {
+ set = function setImmediate(handler) {
+ validateArgumentsLength(arguments.length, 1);
+ var fn = isCallable(handler) ? handler : Function(handler);
+ var args = arraySlice(arguments, 1);
+ queue[++counter] = function () {
+ apply(fn, undefined, args);
+ };
+ defer(counter);
+ return counter;
+ };
+ clear = function clearImmediate(id) {
+ delete queue[id];
+ };
+ // Node.js 0.8-
+ if (IS_NODE) {
+ defer = function (id) {
+ process.nextTick(runner(id));
+ };
+ // Sphere (JS game engine) Dispatch API
+ } else if (Dispatch && Dispatch.now) {
+ defer = function (id) {
+ Dispatch.now(runner(id));
+ };
+ // Browsers with MessageChannel, includes WebWorkers
+ // except iOS - https://github.com/zloirock/core-js/issues/624
+ } else if (MessageChannel && !IS_IOS) {
+ channel = new MessageChannel();
+ port = channel.port2;
+ channel.port1.onmessage = eventListener;
+ defer = bind(port.postMessage, port);
+ // Browsers with postMessage, skip WebWorkers
+ // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
+ } else if (
+ globalThis.addEventListener &&
+ isCallable(globalThis.postMessage) &&
+ !globalThis.importScripts &&
+ $location && $location.protocol !== 'file:' &&
+ !fails(globalPostMessageDefer)
+ ) {
+ defer = globalPostMessageDefer;
+ globalThis.addEventListener('message', eventListener, false);
+ // IE8-
+ } else if (ONREADYSTATECHANGE in createElement('script')) {
+ defer = function (id) {
+ html.appendChild(createElement('script'))[ONREADYSTATECHANGE] = function () {
+ html.removeChild(this);
+ run(id);
+ };
+ };
+ // Rest old browsers
+ } else {
+ defer = function (id) {
+ setTimeout(runner(id), 0);
+ };
+ }
+}
-module.exports = !fails(function () {
- // eslint-disable-next-line es/no-function-prototype-bind -- safe
- var test = (function () { /* empty */ }).bind();
- // eslint-disable-next-line no-prototype-builtins -- safe
- return typeof test != 'function' || test.hasOwnProperty('prototype');
-});
+module.exports = {
+ set: set,
+ clear: clear
+};
/***/ }),
-/* 131 */
+/* 138 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-module.exports = {};
+var uncurryThis = __webpack_require__(2);
+
+// `thisNumberValue` abstract operation
+// https://tc39.es/ecma262/#sec-thisnumbervalue
+module.exports = uncurryThis(1.1.valueOf);
/***/ }),
-/* 132 */
+/* 139 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var fails = __webpack_require__(33);
-var isCallable = __webpack_require__(46);
-
-var replacement = /#|\.prototype\./;
+var toIntegerOrInfinity = __webpack_require__(22);
+var toLength = __webpack_require__(45);
-var isForced = function (feature, detection) {
- var value = data[normalize(feature)];
- return value === POLYFILL ? true
- : value === NATIVE ? false
- : isCallable(detection) ? fails(detection)
- : !!detection;
-};
+var $RangeError = RangeError;
-var normalize = isForced.normalize = function (string) {
- return String(string).replace(replacement, '.').toLowerCase();
+// `ToIndex` abstract operation
+// https://tc39.es/ecma262/#sec-toindex
+module.exports = function (it) {
+ if (it === undefined) return 0;
+ var number = toIntegerOrInfinity(it);
+ var length = toLength(number);
+ if (number !== length) throw new $RangeError('Wrong length or index');
+ return length;
};
-var data = isForced.data = {};
-var NATIVE = isForced.NATIVE = 'N';
-var POLYFILL = isForced.POLYFILL = 'P';
-
-module.exports = isForced;
-
/***/ }),
-/* 133 */
+/* 140 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-module.exports = {};
-
+var call = __webpack_require__(4);
+var isObject = __webpack_require__(8);
+var isSymbol = __webpack_require__(73);
+var getMethod = __webpack_require__(28);
+var ordinaryToPrimitive = __webpack_require__(233);
+var wellKnownSymbol = __webpack_require__(7);
-/***/ }),
-/* 134 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var internalObjectKeys = __webpack_require__(260);
-var enumBugKeys = __webpack_require__(182);
+var $TypeError = TypeError;
+var TO_PRIMITIVE = wellKnownSymbol('toPrimitive');
-// `Object.keys` method
-// https://tc39.es/ecma262/#sec-object.keys
-// eslint-disable-next-line es/no-object-keys -- safe
-module.exports = Object.keys || function keys(O) {
- return internalObjectKeys(O, enumBugKeys);
+// `ToPrimitive` abstract operation
+// https://tc39.es/ecma262/#sec-toprimitive
+module.exports = function (input, pref) {
+ if (!isObject(input) || isSymbol(input)) return input;
+ var exoticToPrim = getMethod(input, TO_PRIMITIVE);
+ var result;
+ if (exoticToPrim) {
+ if (pref === undefined) pref = 'default';
+ result = call(exoticToPrim, input, pref);
+ if (!isObject(result) || isSymbol(result)) return result;
+ throw new $TypeError("Can't convert object to primitive value");
+ }
+ if (pref === undefined) pref = 'number';
+ return ordinaryToPrimitive(input, pref);
};
/***/ }),
-/* 135 */
+/* 141 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var NativePromiseConstructor = __webpack_require__(120);
-var isCallable = __webpack_require__(46);
-var isForced = __webpack_require__(132);
-var inspectSource = __webpack_require__(186);
-var wellKnownSymbol = __webpack_require__(39);
-var ENVIRONMENT = __webpack_require__(149);
-var IS_PURE = __webpack_require__(48);
-var V8_VERSION = __webpack_require__(84);
+var fails = __webpack_require__(1);
+var wellKnownSymbol = __webpack_require__(7);
+var DESCRIPTORS = __webpack_require__(6);
+var IS_PURE = __webpack_require__(16);
-var NativePromisePrototype = NativePromiseConstructor && NativePromiseConstructor.prototype;
-var SPECIES = wellKnownSymbol('species');
-var SUBCLASSING = false;
-var NATIVE_PROMISE_REJECTION_EVENT = isCallable(globalThis.PromiseRejectionEvent);
+var ITERATOR = wellKnownSymbol('iterator');
-var FORCED_PROMISE_CONSTRUCTOR = isForced('Promise', function () {
- var PROMISE_CONSTRUCTOR_SOURCE = inspectSource(NativePromiseConstructor);
- var GLOBAL_CORE_JS_PROMISE = PROMISE_CONSTRUCTOR_SOURCE !== String(NativePromiseConstructor);
- // V8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables
- // https://bugs.chromium.org/p/chromium/issues/detail?id=830565
- // We can't detect it synchronously, so just check versions
- if (!GLOBAL_CORE_JS_PROMISE && V8_VERSION === 66) return true;
- // We need Promise#{ catch, finally } in the pure version for preventing prototype pollution
- if (IS_PURE && !(NativePromisePrototype['catch'] && NativePromisePrototype['finally'])) return true;
- // We can't use @@species feature detection in V8 since it causes
- // deoptimization and performance degradation
- // https://github.com/zloirock/core-js/issues/679
- if (!V8_VERSION || V8_VERSION < 51 || !/native code/.test(PROMISE_CONSTRUCTOR_SOURCE)) {
- // Detect correctness of subclassing with @@species support
- var promise = new NativePromiseConstructor(function (resolve) { resolve(1); });
- var FakePromise = function (exec) {
- exec(function () { /* empty */ }, function () { /* empty */ });
- };
- var constructor = promise.constructor = {};
- constructor[SPECIES] = FakePromise;
- SUBCLASSING = promise.then(function () { /* empty */ }) instanceof FakePromise;
- if (!SUBCLASSING) return true;
- // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
- } return !GLOBAL_CORE_JS_PROMISE && (ENVIRONMENT === 'BROWSER' || ENVIRONMENT === 'DENO') && !NATIVE_PROMISE_REJECTION_EVENT;
+module.exports = !fails(function () {
+ // eslint-disable-next-line unicorn/relative-url-style -- required for testing
+ var url = new URL('b?a=1&b=2&c=3', 'https://a');
+ var params = url.searchParams;
+ var params2 = new URLSearchParams('a=1&a=2&b=3');
+ var result = '';
+ url.pathname = 'c%20d';
+ params.forEach(function (value, key) {
+ params['delete']('b');
+ result += key + value;
+ });
+ params2['delete']('a', 2);
+ // `undefined` case is a Chromium 117 bug
+ // https://bugs.chromium.org/p/v8/issues/detail?id=14222
+ params2['delete']('b', undefined);
+ return (IS_PURE && (!url.toJSON || !params2.has('a', 1) || params2.has('a', 2) || !params2.has('a', undefined) || params2.has('b')))
+ || (!params.size && (IS_PURE || !DESCRIPTORS))
+ || !params.sort
+ || url.href !== 'https://a/c%20d?a=1&c=3'
+ || params.get('c') !== '3'
+ || String(new URLSearchParams('?a=1')) !== 'a=1'
+ || !params[ITERATOR]
+ // throws in Edge
+ || new URL('https://a@b').username !== 'a'
+ || new URLSearchParams(new URLSearchParams('a=b')).get('a') !== 'b'
+ // not punycoded in Edge
+ || new URL('https://тест').host !== 'xn--e1aybc'
+ // not escaped in Chrome 62-
+ || new URL('https://a#б').hash !== '#%D0%B1'
+ // fails in Chrome 66-
+ || result !== 'a1c3'
+ // throws in Safari
+ || new URL('https://x', undefined).host !== 'x';
});
-module.exports = {
- CONSTRUCTOR: FORCED_PROMISE_CONSTRUCTOR,
- REJECTION_EVENT: NATIVE_PROMISE_REJECTION_EVENT,
- SUBCLASSING: SUBCLASSING
-};
-
/***/ }),
-/* 136 */
+/* 142 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var call = __webpack_require__(36);
-var anObject = __webpack_require__(37);
-var isCallable = __webpack_require__(46);
-var classof = __webpack_require__(64);
-var regexpExec = __webpack_require__(198);
+var toIndexedObject = __webpack_require__(25);
+var addToUnscopables = __webpack_require__(37);
+var Iterators = __webpack_require__(102);
+var InternalStateModule = __webpack_require__(21);
+var defineProperty = __webpack_require__(19).f;
+var defineIterator = __webpack_require__(161);
+var createIterResultObject = __webpack_require__(65);
+var IS_PURE = __webpack_require__(16);
+var DESCRIPTORS = __webpack_require__(6);
-var $TypeError = TypeError;
+var ARRAY_ITERATOR = 'Array Iterator';
+var setInternalState = InternalStateModule.set;
+var getInternalState = InternalStateModule.getterFor(ARRAY_ITERATOR);
-// `RegExpExec` abstract operation
-// https://tc39.es/ecma262/#sec-regexpexec
-module.exports = function (R, S) {
- var exec = R.exec;
- if (isCallable(exec)) {
- var result = call(exec, R, S);
- if (result !== null) anObject(result);
- return result;
+// `Array.prototype.entries` method
+// https://tc39.es/ecma262/#sec-array.prototype.entries
+// `Array.prototype.keys` method
+// https://tc39.es/ecma262/#sec-array.prototype.keys
+// `Array.prototype.values` method
+// https://tc39.es/ecma262/#sec-array.prototype.values
+// `Array.prototype[@@iterator]` method
+// https://tc39.es/ecma262/#sec-array.prototype-@@iterator
+// `CreateArrayIterator` internal method
+// https://tc39.es/ecma262/#sec-createarrayiterator
+module.exports = defineIterator(Array, 'Array', function (iterated, kind) {
+ setInternalState(this, {
+ type: ARRAY_ITERATOR,
+ target: toIndexedObject(iterated), // target
+ index: 0, // next index
+ kind: kind // kind
+ });
+// `%ArrayIteratorPrototype%.next` method
+// https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next
+}, function () {
+ var state = getInternalState(this);
+ var target = state.target;
+ var index = state.index++;
+ if (!target || index >= target.length) {
+ state.target = null;
+ return createIterResultObject(undefined, true);
}
- if (classof(R) === 'RegExp') return call(regexpExec, R, S);
- throw new $TypeError('RegExp#exec called on incompatible receiver');
-};
+ switch (state.kind) {
+ case 'keys': return createIterResultObject(index, false);
+ case 'values': return createIterResultObject(target[index], false);
+ } return createIterResultObject([index, target[index]], false);
+}, 'values');
+
+// argumentsList[@@iterator] is %ArrayProto_values%
+// https://tc39.es/ecma262/#sec-createunmappedargumentsobject
+// https://tc39.es/ecma262/#sec-createmappedargumentsobject
+var values = Iterators.Arguments = Iterators.Array;
+
+// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
+addToUnscopables('keys');
+addToUnscopables('values');
+addToUnscopables('entries');
+
+// V8 ~ Chrome 45- bug
+if (!IS_PURE && DESCRIPTORS && values.name !== 'values') try {
+ defineProperty(values, 'name', { value: 'values' });
+} catch (error) { /* empty */ }
/***/ }),
-/* 137 */
+/* 143 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThisAccessor = __webpack_require__(151);
-var SetHelpers = __webpack_require__(82);
-module.exports = uncurryThisAccessor(SetHelpers.proto, 'size', 'get') || function (set) {
- return set.size;
-};
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.requestAudioContext = exports.intervalInRange = exports.roundInterval = exports.clamp = exports.lerp = exports.browser = exports.mod = exports.choice = undefined;
+var _tone = __webpack_require__(108);
-/***/ }),
-/* 138 */
-/***/ (function(module, exports, __webpack_require__) {
+var _tone2 = _interopRequireDefault(_tone);
-"use strict";
+var _startAudioContext = __webpack_require__(271);
-// a string of all valid unicode whitespaces
-module.exports = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' +
- '\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF';
+var _startAudioContext2 = _interopRequireDefault(_startAudioContext);
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-/***/ }),
-/* 139 */
-/***/ (function(module, exports, __webpack_require__) {
+/**
+ * Utilities
+ * @module lib/util.js;
+ */
-"use strict";
+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;
-var charAt = __webpack_require__(164).charAt;
+document.body.classList.add(isMobile ? "mobile" : "desktop");
-// `AdvanceStringIndex` abstract operation
-// https://tc39.es/ecma262/#sec-advancestringindex
-module.exports = function (S, index, unicode) {
- return index + (unicode ? charAt(S, index).length : 1);
+var browser = { isIphone: isIphone, isIpad: isIpad, isMobile: isMobile, isDesktop: isDesktop };
+
+function choice(a) {
+ return a[Math.floor(Math.random() * a.length)];
+}
+function mod(n, m) {
+ return n - m * Math.floor(n / m);
+}
+function roundInterval(interval) {
+ return Math.round(interval * 10000000);
+}
+var intervalInRange = function intervalInRange(interval, root) {
+ return 20 < interval * root && interval * root < 15000;
+};
+var lerp = function lerp(n, a, b) {
+ return (b - a) * n + a;
+};
+var clamp = function clamp(n) {
+ var a = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+ var b = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
+ return n < a ? a : n < b ? n : b;
};
+function requestAudioContext(fn) {
+ if (window.location.protocol !== "https:") {
+ 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.browser = browser;
+exports.lerp = lerp;
+exports.clamp = clamp;
+exports.roundInterval = roundInterval;
+exports.intervalInRange = intervalInRange;
+exports.requestAudioContext = requestAudioContext;
/***/ }),
-/* 140 */
+/* 144 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-// eslint-disable-next-line es/no-typed-arrays -- safe
-module.exports = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';
+var isConstructor = __webpack_require__(72);
+var tryToString = __webpack_require__(78);
+
+var $TypeError = TypeError;
+
+// `Assert: IsConstructor(argument) is true`
+module.exports = function (argument) {
+ if (isConstructor(argument)) return argument;
+ throw new $TypeError(tryToString(argument) + ' is not a constructor');
+};
/***/ }),
-/* 141 */
+/* 145 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var uncurryThis = __webpack_require__(34);
-var DESCRIPTORS = __webpack_require__(38);
-var NATIVE_ARRAY_BUFFER = __webpack_require__(140);
-var FunctionName = __webpack_require__(113);
-var createNonEnumerableProperty = __webpack_require__(59);
-var defineBuiltInAccessor = __webpack_require__(55);
-var defineBuiltIns = __webpack_require__(88);
-var fails = __webpack_require__(33);
-var anInstance = __webpack_require__(71);
-var toIntegerOrInfinity = __webpack_require__(54);
-var toLength = __webpack_require__(77);
-var toIndex = __webpack_require__(169);
-var fround = __webpack_require__(249);
-var IEEE754 = __webpack_require__(301);
-var getPrototypeOf = __webpack_require__(67);
-var setPrototypeOf = __webpack_require__(81);
-var arrayFill = __webpack_require__(175);
-var arraySlice = __webpack_require__(78);
-var inheritIfRequired = __webpack_require__(101);
-var copyConstructorProperties = __webpack_require__(110);
-var setToStringTag = __webpack_require__(70);
-var InternalStateModule = __webpack_require__(53);
-
-var PROPER_FUNCTION_NAME = FunctionName.PROPER;
-var CONFIGURABLE_FUNCTION_NAME = FunctionName.CONFIGURABLE;
-var ARRAY_BUFFER = 'ArrayBuffer';
-var DATA_VIEW = 'DataView';
-var PROTOTYPE = 'prototype';
-var WRONG_LENGTH = 'Wrong length';
-var WRONG_INDEX = 'Wrong index';
-var getInternalArrayBufferState = InternalStateModule.getterFor(ARRAY_BUFFER);
-var getInternalDataViewState = InternalStateModule.getterFor(DATA_VIEW);
-var setInternalState = InternalStateModule.set;
-var NativeArrayBuffer = globalThis[ARRAY_BUFFER];
-var $ArrayBuffer = NativeArrayBuffer;
-var ArrayBufferPrototype = $ArrayBuffer && $ArrayBuffer[PROTOTYPE];
-var $DataView = globalThis[DATA_VIEW];
-var DataViewPrototype = $DataView && $DataView[PROTOTYPE];
-var ObjectPrototype = Object.prototype;
-var Array = globalThis.Array;
-var RangeError = globalThis.RangeError;
-var fill = uncurryThis(arrayFill);
-var reverse = uncurryThis([].reverse);
-
-var packIEEE754 = IEEE754.pack;
-var unpackIEEE754 = IEEE754.unpack;
-
-var packInt8 = function (number) {
- return [number & 0xFF];
-};
-
-var packInt16 = function (number) {
- return [number & 0xFF, number >> 8 & 0xFF];
-};
+// FF26- bug: ArrayBuffers are non-extensible, but Object.isExtensible does not report it
+var fails = __webpack_require__(1);
-var packInt32 = function (number) {
- return [number & 0xFF, number >> 8 & 0xFF, number >> 16 & 0xFF, number >> 24 & 0xFF];
-};
+module.exports = fails(function () {
+ if (typeof ArrayBuffer == 'function') {
+ var buffer = new ArrayBuffer(8);
+ // eslint-disable-next-line es/no-object-isextensible, es/no-object-defineproperty -- safe
+ if (Object.isExtensible(buffer)) Object.defineProperty(buffer, 'a', { value: 8 });
+ }
+});
-var unpackInt32 = function (buffer) {
- return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
-};
-var packFloat32 = function (number) {
- return packIEEE754(fround(number), 23, 4);
-};
+/***/ }),
+/* 146 */
+/***/ (function(module, exports, __webpack_require__) {
-var packFloat64 = function (number) {
- return packIEEE754(number, 52, 8);
-};
+"use strict";
-var addGetter = function (Constructor, key, getInternalState) {
- defineBuiltInAccessor(Constructor[PROTOTYPE], key, {
- configurable: true,
- get: function () {
- return getInternalState(this)[key];
- }
- });
-};
+var toObject = __webpack_require__(15);
+var toAbsoluteIndex = __webpack_require__(59);
+var lengthOfArrayLike = __webpack_require__(18);
-var get = function (view, count, index, isLittleEndian) {
- var store = getInternalDataViewState(view);
- var intIndex = toIndex(index);
- var boolIsLittleEndian = !!isLittleEndian;
- if (intIndex + count > store.byteLength) throw new RangeError(WRONG_INDEX);
- var bytes = store.bytes;
- var start = intIndex + store.byteOffset;
- var pack = arraySlice(bytes, start, start + count);
- return boolIsLittleEndian ? pack : reverse(pack);
+// `Array.prototype.fill` method implementation
+// https://tc39.es/ecma262/#sec-array.prototype.fill
+module.exports = function fill(value /* , start = 0, end = @length */) {
+ var O = toObject(this);
+ var length = lengthOfArrayLike(O);
+ var argumentsLength = arguments.length;
+ var index = toAbsoluteIndex(argumentsLength > 1 ? arguments[1] : undefined, length);
+ var end = argumentsLength > 2 ? arguments[2] : undefined;
+ var endPos = end === undefined ? length : toAbsoluteIndex(end, length);
+ while (endPos > index) O[index++] = value;
+ return O;
};
-var set = function (view, count, index, conversion, value, isLittleEndian) {
- var store = getInternalDataViewState(view);
- var intIndex = toIndex(index);
- var pack = conversion(+value);
- var boolIsLittleEndian = !!isLittleEndian;
- if (intIndex + count > store.byteLength) throw new RangeError(WRONG_INDEX);
- var bytes = store.bytes;
- var start = intIndex + store.byteOffset;
- for (var i = 0; i < count; i++) bytes[start + i] = pack[boolIsLittleEndian ? i : count - i - 1];
-};
-if (!NATIVE_ARRAY_BUFFER) {
- $ArrayBuffer = function ArrayBuffer(length) {
- anInstance(this, ArrayBufferPrototype);
- var byteLength = toIndex(length);
- setInternalState(this, {
- type: ARRAY_BUFFER,
- bytes: fill(Array(byteLength), 0),
- byteLength: byteLength
- });
- if (!DESCRIPTORS) {
- this.byteLength = byteLength;
- this.detached = false;
- }
- };
+/***/ }),
+/* 147 */
+/***/ (function(module, exports, __webpack_require__) {
- ArrayBufferPrototype = $ArrayBuffer[PROTOTYPE];
+"use strict";
- $DataView = function DataView(buffer, byteOffset, byteLength) {
- anInstance(this, DataViewPrototype);
- anInstance(buffer, ArrayBufferPrototype);
- var bufferState = getInternalArrayBufferState(buffer);
- var bufferLength = bufferState.byteLength;
- var offset = toIntegerOrInfinity(byteOffset);
- if (offset < 0 || offset > bufferLength) throw new RangeError('Wrong offset');
- byteLength = byteLength === undefined ? bufferLength - offset : toLength(byteLength);
- if (offset + byteLength > bufferLength) throw new RangeError(WRONG_LENGTH);
- setInternalState(this, {
- type: DATA_VIEW,
- buffer: buffer,
- byteLength: byteLength,
- byteOffset: offset,
- bytes: bufferState.bytes
- });
- if (!DESCRIPTORS) {
- this.buffer = buffer;
- this.byteLength = byteLength;
- this.byteOffset = offset;
- }
- };
+var DESCRIPTORS = __webpack_require__(6);
+var isArray = __webpack_require__(62);
- DataViewPrototype = $DataView[PROTOTYPE];
+var $TypeError = TypeError;
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
- if (DESCRIPTORS) {
- addGetter($ArrayBuffer, 'byteLength', getInternalArrayBufferState);
- addGetter($DataView, 'buffer', getInternalDataViewState);
- addGetter($DataView, 'byteLength', getInternalDataViewState);
- addGetter($DataView, 'byteOffset', getInternalDataViewState);
+// Safari < 13 does not throw an error in this case
+var SILENT_ON_NON_WRITABLE_LENGTH_SET = DESCRIPTORS && !function () {
+ // makes no sense without proper strict mode support
+ if (this !== undefined) return true;
+ try {
+ // eslint-disable-next-line es/no-object-defineproperty -- safe
+ Object.defineProperty([], 'length', { writable: false }).length = 1;
+ } catch (error) {
+ return error instanceof TypeError;
}
+}();
- defineBuiltIns(DataViewPrototype, {
- getInt8: function getInt8(byteOffset) {
- return get(this, 1, byteOffset)[0] << 24 >> 24;
- },
- getUint8: function getUint8(byteOffset) {
- return get(this, 1, byteOffset)[0];
- },
- getInt16: function getInt16(byteOffset /* , littleEndian */) {
- var bytes = get(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : false);
- return (bytes[1] << 8 | bytes[0]) << 16 >> 16;
- },
- getUint16: function getUint16(byteOffset /* , littleEndian */) {
- var bytes = get(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : false);
- return bytes[1] << 8 | bytes[0];
- },
- getInt32: function getInt32(byteOffset /* , littleEndian */) {
- return unpackInt32(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false));
- },
- getUint32: function getUint32(byteOffset /* , littleEndian */) {
- return unpackInt32(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false)) >>> 0;
- },
- getFloat32: function getFloat32(byteOffset /* , littleEndian */) {
- return unpackIEEE754(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false), 23);
- },
- getFloat64: function getFloat64(byteOffset /* , littleEndian */) {
- return unpackIEEE754(get(this, 8, byteOffset, arguments.length > 1 ? arguments[1] : false), 52);
- },
- setInt8: function setInt8(byteOffset, value) {
- set(this, 1, byteOffset, packInt8, value);
- },
- setUint8: function setUint8(byteOffset, value) {
- set(this, 1, byteOffset, packInt8, value);
- },
- setInt16: function setInt16(byteOffset, value /* , littleEndian */) {
- set(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : false);
- },
- setUint16: function setUint16(byteOffset, value /* , littleEndian */) {
- set(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : false);
- },
- setInt32: function setInt32(byteOffset, value /* , littleEndian */) {
- set(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : false);
- },
- setUint32: function setUint32(byteOffset, value /* , littleEndian */) {
- set(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : false);
- },
- setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) {
- set(this, 4, byteOffset, packFloat32, value, arguments.length > 2 ? arguments[2] : false);
- },
- setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) {
- set(this, 8, byteOffset, packFloat64, value, arguments.length > 2 ? arguments[2] : false);
- }
- });
-} else {
- var INCORRECT_ARRAY_BUFFER_NAME = PROPER_FUNCTION_NAME && NativeArrayBuffer.name !== ARRAY_BUFFER;
- /* eslint-disable no-new, sonarjs/inconsistent-function-call -- required for testing */
- if (!fails(function () {
- NativeArrayBuffer(1);
- }) || !fails(function () {
- new NativeArrayBuffer(-1);
- }) || fails(function () {
- new NativeArrayBuffer();
- new NativeArrayBuffer(1.5);
- new NativeArrayBuffer(NaN);
- return NativeArrayBuffer.length !== 1 || INCORRECT_ARRAY_BUFFER_NAME && !CONFIGURABLE_FUNCTION_NAME;
- })) {
- /* eslint-enable no-new, sonarjs/inconsistent-function-call -- required for testing */
- $ArrayBuffer = function ArrayBuffer(length) {
- anInstance(this, ArrayBufferPrototype);
- return inheritIfRequired(new NativeArrayBuffer(toIndex(length)), this, $ArrayBuffer);
- };
+module.exports = SILENT_ON_NON_WRITABLE_LENGTH_SET ? function (O, length) {
+ if (isArray(O) && !getOwnPropertyDescriptor(O, 'length').writable) {
+ throw new $TypeError('Cannot set read only .length');
+ } return O.length = length;
+} : function (O, length) {
+ return O.length = length;
+};
- $ArrayBuffer[PROTOTYPE] = ArrayBufferPrototype;
- ArrayBufferPrototype.constructor = $ArrayBuffer;
+/***/ }),
+/* 148 */
+/***/ (function(module, exports, __webpack_require__) {
- copyConstructorProperties($ArrayBuffer, NativeArrayBuffer);
- } else if (INCORRECT_ARRAY_BUFFER_NAME && CONFIGURABLE_FUNCTION_NAME) {
- createNonEnumerableProperty(NativeArrayBuffer, 'name', ARRAY_BUFFER);
- }
+"use strict";
- // WebKit bug - the same parent prototype for typed arrays and data view
- if (setPrototypeOf && getPrototypeOf(DataViewPrototype) !== ObjectPrototype) {
- setPrototypeOf(DataViewPrototype, ObjectPrototype);
- }
+var arraySlice = __webpack_require__(46);
- // iOS Safari 7.x bug
- var testView = new $DataView(new $ArrayBuffer(2));
- var $setInt8 = uncurryThis(DataViewPrototype.setInt8);
- testView.setInt8(0, 2147483648);
- testView.setInt8(1, 2147483649);
- if (testView.getInt8(0) || !testView.getInt8(1)) defineBuiltIns(DataViewPrototype, {
- setInt8: function setInt8(byteOffset, value) {
- $setInt8(this, byteOffset, value << 24 >> 24);
- },
- setUint8: function setUint8(byteOffset, value) {
- $setInt8(this, byteOffset, value << 24 >> 24);
+var floor = Math.floor;
+
+var sort = function (array, comparefn) {
+ var length = array.length;
+
+ if (length < 8) {
+ // insertion sort
+ var i = 1;
+ var element, j;
+
+ while (i < length) {
+ j = i;
+ element = array[i];
+ while (j && comparefn(array[j - 1], element) > 0) {
+ array[j] = array[--j];
+ }
+ if (j !== i++) array[j] = element;
}
- }, { unsafe: true });
-}
+ } else {
+ // merge sort
+ var middle = floor(length / 2);
+ var left = sort(arraySlice(array, 0, middle), comparefn);
+ var right = sort(arraySlice(array, middle), comparefn);
+ var llength = left.length;
+ var rlength = right.length;
+ var lindex = 0;
+ var rindex = 0;
-setToStringTag($ArrayBuffer, ARRAY_BUFFER);
-setToStringTag($DataView, DATA_VIEW);
+ while (lindex < llength || rindex < rlength) {
+ array[lindex + rindex] = (lindex < llength && rindex < rlength)
+ ? comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++]
+ : lindex < llength ? left[lindex++] : right[rindex++];
+ }
+ }
-module.exports = {
- ArrayBuffer: $ArrayBuffer,
- DataView: $DataView
+ return array;
};
+module.exports = sort;
+
/***/ }),
-/* 142 */
+/* 149 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var lengthOfArrayLike = __webpack_require__(50);
+var anObject = __webpack_require__(5);
+var iteratorClose = __webpack_require__(29);
-module.exports = function (Constructor, list, $length) {
- var index = 0;
- var length = arguments.length > 2 ? $length : lengthOfArrayLike(list);
- var result = new Constructor(length);
- while (length > index) result[index] = list[index++];
- return result;
+// call something on iterator step with safe closing on error
+module.exports = function (iterator, fn, value, ENTRIES) {
+ try {
+ return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value);
+ } catch (error) {
+ iteratorClose(iterator, 'throw', error);
+ }
};
/***/ }),
-/* 143 */
+/* 150 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var bind = __webpack_require__(75);
-var IndexedObject = __webpack_require__(115);
-var toObject = __webpack_require__(47);
-var lengthOfArrayLike = __webpack_require__(50);
+var wellKnownSymbol = __webpack_require__(7);
-// `Array.prototype.{ findLast, findLastIndex }` methods implementation
-var createMethod = function (TYPE) {
- var IS_FIND_LAST_INDEX = TYPE === 1;
- return function ($this, callbackfn, that) {
- var O = toObject($this);
- var self = IndexedObject(O);
- var index = lengthOfArrayLike(self);
- var boundFunction = bind(callbackfn, that);
- var value, result;
- while (index-- > 0) {
- value = self[index];
- result = boundFunction(value, index, O);
- if (result) switch (TYPE) {
- case 0: return value; // findLast
- case 1: return index; // findLastIndex
- }
- }
- return IS_FIND_LAST_INDEX ? -1 : undefined;
- };
-};
+var MATCH = wellKnownSymbol('match');
-module.exports = {
- // `Array.prototype.findLast` method
- // https://github.com/tc39/proposal-array-find-from-last
- findLast: createMethod(0),
- // `Array.prototype.findLastIndex` method
- // https://github.com/tc39/proposal-array-find-from-last
- findLastIndex: createMethod(1)
+module.exports = function (METHOD_NAME) {
+ var regexp = /./;
+ try {
+ '/./'[METHOD_NAME](regexp);
+ } catch (error1) {
+ try {
+ regexp[MATCH] = false;
+ return '/./'[METHOD_NAME](regexp);
+ } catch (error2) { /* empty */ }
+ } return false;
};
/***/ }),
-/* 144 */
+/* 151 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var aCallable = __webpack_require__(42);
-var toObject = __webpack_require__(47);
-var IndexedObject = __webpack_require__(115);
-var lengthOfArrayLike = __webpack_require__(50);
-
-var $TypeError = TypeError;
-
-var REDUCE_EMPTY = 'Reduce of empty array with no initial value';
-
-// `Array.prototype.{ reduce, reduceRight }` methods implementation
-var createMethod = function (IS_RIGHT) {
- return function (that, callbackfn, argumentsLength, memo) {
- var O = toObject(that);
- var self = IndexedObject(O);
- var length = lengthOfArrayLike(O);
- aCallable(callbackfn);
- if (length === 0 && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);
- var index = IS_RIGHT ? length - 1 : 0;
- var i = IS_RIGHT ? -1 : 1;
- if (argumentsLength < 2) while (true) {
- if (index in self) {
- memo = self[index];
- index += i;
- break;
- }
- index += i;
- if (IS_RIGHT ? index < 0 : length <= index) {
- throw new $TypeError(REDUCE_EMPTY);
- }
- }
- for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {
- memo = callbackfn(memo, self[index], index, O);
- }
- return memo;
- };
-};
+var fails = __webpack_require__(1);
-module.exports = {
- // `Array.prototype.reduce` method
- // https://tc39.es/ecma262/#sec-array.prototype.reduce
- left: createMethod(false),
- // `Array.prototype.reduceRight` method
- // https://tc39.es/ecma262/#sec-array.prototype.reduceright
- right: createMethod(true)
-};
+module.exports = !fails(function () {
+ function F() { /* empty */ }
+ F.prototype.constructor = null;
+ // eslint-disable-next-line es/no-object-getprototypeof -- required for testing
+ return Object.getPrototypeOf(new F()) !== F.prototype;
+});
/***/ }),
-/* 145 */
+/* 152 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var wellKnownSymbol = __webpack_require__(39);
-
-var ITERATOR = wellKnownSymbol('iterator');
-var SAFE_CLOSING = false;
+var globalThis = __webpack_require__(3);
-try {
- var called = 0;
- var iteratorWithReturn = {
- next: function () {
- return { done: !!called++ };
- },
- 'return': function () {
- SAFE_CLOSING = true;
- }
- };
- iteratorWithReturn[ITERATOR] = function () {
- return this;
- };
- // eslint-disable-next-line es/no-array-from, no-throw-literal -- required for testing
- Array.from(iteratorWithReturn, function () { throw 2; });
-} catch (error) { /* empty */ }
+// eslint-disable-next-line es/no-object-defineproperty -- safe
+var defineProperty = Object.defineProperty;
-module.exports = function (exec, SKIP_CLOSING) {
- try {
- if (!SKIP_CLOSING && !SAFE_CLOSING) return false;
- } catch (error) { return false; } // workaround of old WebKit + `eval` bug
- var ITERATION_SUPPORT = false;
+module.exports = function (key, value) {
try {
- var object = {};
- object[ITERATOR] = function () {
- return {
- next: function () {
- return { done: ITERATION_SUPPORT = true };
- }
- };
- };
- exec(object);
- } catch (error) { /* empty */ }
- return ITERATION_SUPPORT;
+ defineProperty(globalThis, key, { value: value, configurable: true, writable: true });
+ } catch (error) {
+ globalThis[key] = value;
+ } return value;
};
/***/ }),
-/* 146 */
+/* 153 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var $ = __webpack_require__(32);
-var globalThis = __webpack_require__(35);
-var uncurryThis = __webpack_require__(34);
-var isForced = __webpack_require__(132);
-var defineBuiltIn = __webpack_require__(49);
-var InternalMetadataModule = __webpack_require__(102);
-var iterate = __webpack_require__(56);
-var anInstance = __webpack_require__(71);
-var isCallable = __webpack_require__(46);
-var isNullOrUndefined = __webpack_require__(89);
-var isObject = __webpack_require__(40);
-var fails = __webpack_require__(33);
-var checkCorrectnessOfIteration = __webpack_require__(145);
-var setToStringTag = __webpack_require__(70);
-var inheritIfRequired = __webpack_require__(101);
+// IE8- don't enum bug keys
+module.exports = [
+ 'constructor',
+ 'hasOwnProperty',
+ 'isPrototypeOf',
+ 'propertyIsEnumerable',
+ 'toLocaleString',
+ 'toString',
+ 'valueOf'
+];
-module.exports = function (CONSTRUCTOR_NAME, wrapper, common) {
- var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;
- var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;
- var ADDER = IS_MAP ? 'set' : 'add';
- var NativeConstructor = globalThis[CONSTRUCTOR_NAME];
- var NativePrototype = NativeConstructor && NativeConstructor.prototype;
- var Constructor = NativeConstructor;
- var exported = {};
- var fixMethod = function (KEY) {
- var uncurriedNativeMethod = uncurryThis(NativePrototype[KEY]);
- defineBuiltIn(NativePrototype, KEY,
- KEY === 'add' ? function add(value) {
- uncurriedNativeMethod(this, value === 0 ? 0 : value);
- return this;
- } : KEY === 'delete' ? function (key) {
- return IS_WEAK && !isObject(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
- } : KEY === 'get' ? function get(key) {
- return IS_WEAK && !isObject(key) ? undefined : uncurriedNativeMethod(this, key === 0 ? 0 : key);
- } : KEY === 'has' ? function has(key) {
- return IS_WEAK && !isObject(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
- } : function set(key, value) {
- uncurriedNativeMethod(this, key === 0 ? 0 : key, value);
- return this;
- }
- );
- };
+/***/ }),
+/* 154 */
+/***/ (function(module, exports, __webpack_require__) {
- var REPLACE = isForced(
- CONSTRUCTOR_NAME,
- !isCallable(NativeConstructor) || !(IS_WEAK || NativePrototype.forEach && !fails(function () {
- new NativeConstructor().entries().next();
- }))
- );
+"use strict";
- if (REPLACE) {
- // create collection constructor
- Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER);
- InternalMetadataModule.enable();
- } else if (isForced(CONSTRUCTOR_NAME, true)) {
- var instance = new Constructor();
- // early implementations not supports chaining
- var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) !== instance;
- // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false
- var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });
- // most early implementations doesn't supports iterables, most modern - not close it correctly
- // eslint-disable-next-line no-new -- required for testing
- var ACCEPT_ITERABLES = checkCorrectnessOfIteration(function (iterable) { new NativeConstructor(iterable); });
- // for early implementations -0 and +0 not the same
- var BUGGY_ZERO = !IS_WEAK && fails(function () {
- // V8 ~ Chromium 42- fails only with 5+ elements
- var $instance = new NativeConstructor();
- var index = 5;
- while (index--) $instance[ADDER](index, index);
- return !$instance.has(-0);
- });
+var userAgent = __webpack_require__(51);
- if (!ACCEPT_ITERABLES) {
- Constructor = wrapper(function (dummy, iterable) {
- anInstance(dummy, NativePrototype);
- var that = inheritIfRequired(new NativeConstructor(), dummy, Constructor);
- if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
- return that;
- });
- Constructor.prototype = NativePrototype;
- NativePrototype.constructor = Constructor;
- }
+var webkit = userAgent.match(/AppleWebKit\/(\d+)\./);
+
+module.exports = !!webkit && +webkit[1];
+
+
+/***/ }),
+/* 155 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+var uncurryThis = __webpack_require__(2);
+
+var $Error = Error;
+var replace = uncurryThis(''.replace);
+
+var TEST = (function (arg) { return String(new $Error(arg).stack); })('zxcasd');
+// eslint-disable-next-line redos/no-vulnerable, sonarjs/slow-regex -- safe
+var V8_OR_CHAKRA_STACK_ENTRY = /\n\s*at [^:]*:[^\n]*/;
+var IS_V8_OR_CHAKRA_STACK = V8_OR_CHAKRA_STACK_ENTRY.test(TEST);
- if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
- fixMethod('delete');
- fixMethod('has');
- IS_MAP && fixMethod('get');
- }
+module.exports = function (stack, dropEntries) {
+ if (IS_V8_OR_CHAKRA_STACK && typeof stack == 'string' && !$Error.prepareStackTrace) {
+ while (dropEntries--) stack = replace(stack, V8_OR_CHAKRA_STACK_ENTRY, '');
+ } return stack;
+};
- if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
- // weak collections should not contains .clear method
- if (IS_WEAK && NativePrototype.clear) delete NativePrototype.clear;
- }
+/***/ }),
+/* 156 */
+/***/ (function(module, exports, __webpack_require__) {
- exported[CONSTRUCTOR_NAME] = Constructor;
- $({ global: true, constructor: true, forced: Constructor !== NativeConstructor }, exported);
+"use strict";
- setToStringTag(Constructor, CONSTRUCTOR_NAME);
+var createNonEnumerableProperty = __webpack_require__(27);
+var clearErrorStack = __webpack_require__(155);
+var ERROR_STACK_INSTALLABLE = __webpack_require__(204);
- if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP);
+// non-standard V8
+// eslint-disable-next-line es/no-nonstandard-error-properties -- safe
+var captureStackTrace = Error.captureStackTrace;
- return Constructor;
+module.exports = function (error, C, stack, dropEntries) {
+ if (ERROR_STACK_INSTALLABLE) {
+ if (captureStackTrace) captureStackTrace(error, C);
+ else createNonEnumerableProperty(error, 'stack', clearErrorStack(stack, dropEntries));
+ }
};
/***/ }),
-/* 147 */
+/* 157 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var tryToString = __webpack_require__(109);
+var uncurryThis = __webpack_require__(2);
+var isCallable = __webpack_require__(14);
+var store = __webpack_require__(132);
-var $TypeError = TypeError;
+var functionToString = uncurryThis(Function.toString);
-module.exports = function (O, P) {
- if (!delete O[P]) throw new $TypeError('Cannot delete property ' + tryToString(P) + ' of ' + tryToString(O));
-};
+// this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper
+if (!isCallable(store.inspectSource)) {
+ store.inspectSource = function (it) {
+ return functionToString(it);
+ };
+}
+
+module.exports = store.inspectSource;
/***/ }),
-/* 148 */
+/* 158 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var isObject = __webpack_require__(40);
+var wellKnownSymbol = __webpack_require__(7);
+var Iterators = __webpack_require__(102);
-var document = globalThis.document;
-// typeof document.createElement is 'object' in old IE
-var EXISTS = isObject(document) && isObject(document.createElement);
+var ITERATOR = wellKnownSymbol('iterator');
+var ArrayPrototype = Array.prototype;
+// check on default Array iterator
module.exports = function (it) {
- return EXISTS ? document.createElement(it) : {};
+ return it !== undefined && (Iterators.Array === it || ArrayPrototype[ITERATOR] === it);
};
/***/ }),
-/* 149 */
+/* 159 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-/* global Bun, Deno -- detection */
-var globalThis = __webpack_require__(35);
-var userAgent = __webpack_require__(83);
-var classof = __webpack_require__(64);
+var isObject = __webpack_require__(8);
-var userAgentStartsWith = function (string) {
- return userAgent.slice(0, string.length) === string;
+var floor = Math.floor;
+
+// `IsIntegralNumber` abstract operation
+// https://tc39.es/ecma262/#sec-isintegralnumber
+// eslint-disable-next-line es/no-number-isinteger -- safe
+module.exports = Number.isInteger || function isInteger(it) {
+ return !isObject(it) && isFinite(it) && floor(it) === it;
};
-module.exports = (function () {
- if (userAgentStartsWith('Bun/')) return 'BUN';
- if (userAgentStartsWith('Cloudflare-Workers')) return 'CLOUDFLARE';
- if (userAgentStartsWith('Deno/')) return 'DENO';
- if (userAgentStartsWith('Node.js/')) return 'NODE';
- if (globalThis.Bun && typeof Bun.version == 'string') return 'BUN';
- if (globalThis.Deno && typeof Deno.version == 'object') return 'DENO';
- if (classof(globalThis.process) === 'process') return 'NODE';
- if (globalThis.window && globalThis.document) return 'BROWSER';
- return 'REST';
-})();
+
+/***/ }),
+/* 160 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+var IteratorPrototype = __webpack_require__(86).IteratorPrototype;
+var create = __webpack_require__(30);
+var createPropertyDescriptor = __webpack_require__(41);
+var setToStringTag = __webpack_require__(38);
+var Iterators = __webpack_require__(102);
+
+var returnThis = function () { return this; };
+
+module.exports = function (IteratorConstructor, NAME, next, ENUMERABLE_NEXT) {
+ var TO_STRING_TAG = NAME + ' Iterator';
+ IteratorConstructor.prototype = create(IteratorPrototype, { next: createPropertyDescriptor(+!ENUMERABLE_NEXT, next) });
+ setToStringTag(IteratorConstructor, TO_STRING_TAG, false, true);
+ Iterators[TO_STRING_TAG] = returnThis;
+ return IteratorConstructor;
+};
/***/ }),
-/* 150 */
+/* 161 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-// TODO: Remove from `core-js@4` since it's moved to entry points
-__webpack_require__(209);
-var call = __webpack_require__(36);
-var defineBuiltIn = __webpack_require__(49);
-var regexpExec = __webpack_require__(198);
-var fails = __webpack_require__(33);
-var wellKnownSymbol = __webpack_require__(39);
-var createNonEnumerableProperty = __webpack_require__(59);
+var $ = __webpack_require__(0);
+var call = __webpack_require__(4);
+var IS_PURE = __webpack_require__(16);
+var FunctionName = __webpack_require__(82);
+var isCallable = __webpack_require__(14);
+var createIteratorConstructor = __webpack_require__(160);
+var getPrototypeOf = __webpack_require__(35);
+var setPrototypeOf = __webpack_require__(49);
+var setToStringTag = __webpack_require__(38);
+var createNonEnumerableProperty = __webpack_require__(27);
+var defineBuiltIn = __webpack_require__(17);
+var wellKnownSymbol = __webpack_require__(7);
+var Iterators = __webpack_require__(102);
+var IteratorsCore = __webpack_require__(86);
-var SPECIES = wellKnownSymbol('species');
-var RegExpPrototype = RegExp.prototype;
+var PROPER_FUNCTION_NAME = FunctionName.PROPER;
+var CONFIGURABLE_FUNCTION_NAME = FunctionName.CONFIGURABLE;
+var IteratorPrototype = IteratorsCore.IteratorPrototype;
+var BUGGY_SAFARI_ITERATORS = IteratorsCore.BUGGY_SAFARI_ITERATORS;
+var ITERATOR = wellKnownSymbol('iterator');
+var KEYS = 'keys';
+var VALUES = 'values';
+var ENTRIES = 'entries';
-module.exports = function (KEY, exec, FORCED, SHAM) {
- var SYMBOL = wellKnownSymbol(KEY);
+var returnThis = function () { return this; };
- var DELEGATES_TO_SYMBOL = !fails(function () {
- // String methods call symbol-named RegExp methods
- var O = {};
- O[SYMBOL] = function () { return 7; };
- return ''[KEY](O) !== 7;
- });
+module.exports = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
+ createIteratorConstructor(IteratorConstructor, NAME, next);
- var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails(function () {
- // Symbol-named RegExp methods call .exec
- var execCalled = false;
- var re = /a/;
+ var getIterationMethod = function (KIND) {
+ if (KIND === DEFAULT && defaultIterator) return defaultIterator;
+ if (!BUGGY_SAFARI_ITERATORS && KIND && KIND in IterablePrototype) return IterablePrototype[KIND];
- if (KEY === 'split') {
- // We can't use real regex here since it causes deoptimization
- // and serious performance degradation in V8
- // https://github.com/zloirock/core-js/issues/306
- re = {};
- // RegExp[@@split] doesn't call the regex's exec method, but first creates
- // a new one. We need to return the patched regex when creating the new one.
- re.constructor = {};
- re.constructor[SPECIES] = function () { return re; };
- re.flags = '';
- re[SYMBOL] = /./[SYMBOL];
+ switch (KIND) {
+ case KEYS: return function keys() { return new IteratorConstructor(this, KIND); };
+ case VALUES: return function values() { return new IteratorConstructor(this, KIND); };
+ case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); };
}
- re.exec = function () {
- execCalled = true;
- return null;
- };
+ return function () { return new IteratorConstructor(this); };
+ };
- re[SYMBOL]('');
- return !execCalled;
- });
+ var TO_STRING_TAG = NAME + ' Iterator';
+ var INCORRECT_VALUES_NAME = false;
+ var IterablePrototype = Iterable.prototype;
+ var nativeIterator = IterablePrototype[ITERATOR]
+ || IterablePrototype['@@iterator']
+ || DEFAULT && IterablePrototype[DEFAULT];
+ var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT);
+ var anyNativeIterator = NAME === 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
+ var CurrentIteratorPrototype, methods, KEY;
- if (
- !DELEGATES_TO_SYMBOL ||
- !DELEGATES_TO_EXEC ||
- FORCED
- ) {
- var nativeRegExpMethod = /./[SYMBOL];
- var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) {
- var $exec = regexp.exec;
- if ($exec === regexpExec || $exec === RegExpPrototype.exec) {
- if (DELEGATES_TO_SYMBOL && !forceStringMethod) {
- // The native String method already delegates to @@method (this
- // polyfilled function), leasing to infinite recursion.
- // We avoid it by directly calling the native @@method method.
- return { done: true, value: call(nativeRegExpMethod, regexp, str, arg2) };
+ // fix native
+ if (anyNativeIterator) {
+ CurrentIteratorPrototype = getPrototypeOf(anyNativeIterator.call(new Iterable()));
+ if (CurrentIteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {
+ if (!IS_PURE && getPrototypeOf(CurrentIteratorPrototype) !== IteratorPrototype) {
+ if (setPrototypeOf) {
+ setPrototypeOf(CurrentIteratorPrototype, IteratorPrototype);
+ } else if (!isCallable(CurrentIteratorPrototype[ITERATOR])) {
+ defineBuiltIn(CurrentIteratorPrototype, ITERATOR, returnThis);
}
- return { done: true, value: call(nativeMethod, str, regexp, arg2) };
}
- return { done: false };
- });
+ // Set @@toStringTag to native iterators
+ setToStringTag(CurrentIteratorPrototype, TO_STRING_TAG, true, true);
+ if (IS_PURE) Iterators[TO_STRING_TAG] = returnThis;
+ }
+ }
- defineBuiltIn(String.prototype, KEY, methods[0]);
- defineBuiltIn(RegExpPrototype, SYMBOL, methods[1]);
+ // fix Array.prototype.{ values, @@iterator }.name in V8 / FF
+ if (PROPER_FUNCTION_NAME && DEFAULT === VALUES && nativeIterator && nativeIterator.name !== VALUES) {
+ if (!IS_PURE && CONFIGURABLE_FUNCTION_NAME) {
+ createNonEnumerableProperty(IterablePrototype, 'name', VALUES);
+ } else {
+ INCORRECT_VALUES_NAME = true;
+ defaultIterator = function values() { return call(nativeIterator, this); };
+ }
}
- if (SHAM) createNonEnumerableProperty(RegExpPrototype[SYMBOL], 'sham', true);
+ // export additional methods
+ if (DEFAULT) {
+ methods = {
+ values: getIterationMethod(VALUES),
+ keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),
+ entries: getIterationMethod(ENTRIES)
+ };
+ if (FORCED) for (KEY in methods) {
+ if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
+ defineBuiltIn(IterablePrototype, KEY, methods[KEY]);
+ }
+ } else $({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
+ }
+
+ // define iterator
+ if ((!IS_PURE || FORCED) && IterablePrototype[ITERATOR] !== defaultIterator) {
+ defineBuiltIn(IterablePrototype, ITERATOR, defaultIterator, { name: DEFAULT });
+ }
+ Iterators[NAME] = defaultIterator;
+
+ return methods;
};
/***/ }),
-/* 151 */
+/* 162 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
-var aCallable = __webpack_require__(42);
+var uncurryThis = __webpack_require__(2);
+var fails = __webpack_require__(1);
+var isCallable = __webpack_require__(14);
+var hasOwn = __webpack_require__(13);
+var DESCRIPTORS = __webpack_require__(6);
+var CONFIGURABLE_FUNCTION_NAME = __webpack_require__(82).CONFIGURABLE;
+var inspectSource = __webpack_require__(157);
+var InternalStateModule = __webpack_require__(21);
-module.exports = function (object, key, method) {
+var enforceInternalState = InternalStateModule.enforce;
+var getInternalState = InternalStateModule.get;
+var $String = String;
+// eslint-disable-next-line es/no-object-defineproperty -- safe
+var defineProperty = Object.defineProperty;
+var stringSlice = uncurryThis(''.slice);
+var replace = uncurryThis(''.replace);
+var join = uncurryThis([].join);
+
+var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function () {
+ return defineProperty(function () { /* empty */ }, 'length', { value: 8 }).length !== 8;
+});
+
+var TEMPLATE = String(String).split('String');
+
+var makeBuiltIn = module.exports = function (value, name, options) {
+ if (stringSlice($String(name), 0, 7) === 'Symbol(') {
+ name = '[' + replace($String(name), /^Symbol\(([^)]*)\).*$/, '$1') + ']';
+ }
+ if (options && options.getter) name = 'get ' + name;
+ if (options && options.setter) name = 'set ' + name;
+ if (!hasOwn(value, 'name') || (CONFIGURABLE_FUNCTION_NAME && value.name !== name)) {
+ if (DESCRIPTORS) defineProperty(value, 'name', { value: name, configurable: true });
+ else value.name = name;
+ }
+ if (CONFIGURABLE_LENGTH && options && hasOwn(options, 'arity') && value.length !== options.arity) {
+ defineProperty(value, 'length', { value: options.arity });
+ }
try {
- // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
- return uncurryThis(aCallable(Object.getOwnPropertyDescriptor(object, key)[method]));
+ if (options && hasOwn(options, 'constructor') && options.constructor) {
+ if (DESCRIPTORS) defineProperty(value, 'prototype', { writable: false });
+ // in V8 ~ Chrome 53, prototypes of some methods, like `Array.prototype.values`, are non-writable
+ } else if (value.prototype) value.prototype = undefined;
} catch (error) { /* empty */ }
+ var state = enforceInternalState(value);
+ if (!hasOwn(state, 'source')) {
+ state.source = join(TEMPLATE, typeof name == 'string' ? name : '');
+ } return value;
};
+// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
+// eslint-disable-next-line no-extend-native -- required
+Function.prototype.toString = makeBuiltIn(function toString() {
+ return isCallable(this) && getInternalState(this).source || inspectSource(this);
+}, 'toString');
+
/***/ }),
-/* 152 */
+/* 163 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isObject = __webpack_require__(40);
-var classof = __webpack_require__(64);
-var wellKnownSymbol = __webpack_require__(39);
-
-var MATCH = wellKnownSymbol('match');
-
-// `IsRegExp` abstract operation
-// https://tc39.es/ecma262/#sec-isregexp
-module.exports = function (it) {
- var isRegExp;
- return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : classof(it) === 'RegExp');
+// `Math.sign` method implementation
+// https://tc39.es/ecma262/#sec-math.sign
+// eslint-disable-next-line es/no-math-sign -- safe
+module.exports = Math.sign || function sign(x) {
+ var n = +x;
+ // eslint-disable-next-line no-self-compare -- NaN check
+ return n === 0 || n !== n ? n : n < 0 ? -1 : 1;
};
/***/ }),
-/* 153 */
+/* 164 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-// Should throw an error on invalid iterator
-// https://issues.chromium.org/issues/336839115
-module.exports = function (methodName, argument) {
- // eslint-disable-next-line es/no-iterator -- required for testing
- var method = typeof Iterator == 'function' && Iterator.prototype[methodName];
- if (method) try {
- method.call({ next: null }, argument).next();
- } catch (error) {
- return true;
- }
+var isRegExp = __webpack_require__(122);
+
+var $TypeError = TypeError;
+
+module.exports = function (it) {
+ if (isRegExp(it)) {
+ throw new $TypeError("The method doesn't accept regular expressions");
+ } return it;
};
/***/ }),
-/* 154 */
+/* 165 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-// eslint-disable-next-line es/no-math-expm1 -- safe
-var $expm1 = Math.expm1;
-var exp = Math.exp;
+var DESCRIPTORS = __webpack_require__(6);
+var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__(250);
+var definePropertyModule = __webpack_require__(19);
+var anObject = __webpack_require__(5);
+var toIndexedObject = __webpack_require__(25);
+var objectKeys = __webpack_require__(103);
-// `Math.expm1` method implementation
-// https://tc39.es/ecma262/#sec-math.expm1
-module.exports = (!$expm1
- // Old FF bug
- // eslint-disable-next-line no-loss-of-precision -- required for old engines
- || $expm1(10) > 22025.465794806719 || $expm1(10) < 22025.4657948067165168
- // Tor Browser bug
- || $expm1(-2e-17) !== -2e-17
-) ? function expm1(x) {
- var n = +x;
- return n === 0 ? n : n > -1e-6 && n < 1e-6 ? n + n * n / 2 : exp(n) - 1;
-} : $expm1;
+// `Object.defineProperties` method
+// https://tc39.es/ecma262/#sec-object.defineproperties
+// eslint-disable-next-line es/no-object-defineproperties -- safe
+exports.f = DESCRIPTORS && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) {
+ anObject(O);
+ var props = toIndexedObject(Properties);
+ var keys = objectKeys(Properties);
+ var length = keys.length;
+ var index = 0;
+ var key;
+ while (length > index) definePropertyModule.f(O, key = keys[index++], props[key]);
+ return O;
+};
/***/ }),
-/* 155 */
+/* 166 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-// eslint-disable-next-line es/no-object-getownpropertysymbols -- safe
-exports.f = Object.getOwnPropertySymbols;
+/* eslint-disable es/no-object-getownpropertynames -- safe */
+var classof = __webpack_require__(32);
+var toIndexedObject = __webpack_require__(25);
+var $getOwnPropertyNames = __webpack_require__(75).f;
+var arraySlice = __webpack_require__(46);
+
+var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames
+ ? Object.getOwnPropertyNames(window) : [];
+
+var getWindowNames = function (it) {
+ try {
+ return $getOwnPropertyNames(it);
+ } catch (error) {
+ return arraySlice(windowNames);
+ }
+};
+
+// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
+module.exports.f = function getOwnPropertyNames(it) {
+ return windowNames && classof(it) === 'Window'
+ ? getWindowNames(it)
+ : $getOwnPropertyNames(toIndexedObject(it));
+};
/***/ }),
-/* 156 */
+/* 167 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var $propertyIsEnumerable = {}.propertyIsEnumerable;
-// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
-var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+var fails = __webpack_require__(1);
+var isObject = __webpack_require__(8);
+var classof = __webpack_require__(32);
+var ARRAY_BUFFER_NON_EXTENSIBLE = __webpack_require__(145);
-// Nashorn ~ JDK8 bug
-var NASHORN_BUG = getOwnPropertyDescriptor && !$propertyIsEnumerable.call({ 1: 2 }, 1);
+// eslint-disable-next-line es/no-object-isextensible -- safe
+var $isExtensible = Object.isExtensible;
+var FAILS_ON_PRIMITIVES = fails(function () { $isExtensible(1); });
-// `Object.prototype.propertyIsEnumerable` method implementation
-// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
-exports.f = NASHORN_BUG ? function propertyIsEnumerable(V) {
- var descriptor = getOwnPropertyDescriptor(this, V);
- return !!descriptor && descriptor.enumerable;
-} : $propertyIsEnumerable;
+// `Object.isExtensible` method
+// https://tc39.es/ecma262/#sec-object.isextensible
+module.exports = (FAILS_ON_PRIMITIVES || ARRAY_BUFFER_NON_EXTENSIBLE) ? function isExtensible(it) {
+ if (!isObject(it)) return false;
+ if (ARRAY_BUFFER_NON_EXTENSIBLE && classof(it) === 'ArrayBuffer') return false;
+ return $isExtensible ? $isExtensible(it) : true;
+} : $isExtensible;
/***/ }),
-/* 157 */
+/* 168 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-/* eslint-disable no-undef, no-useless-call, sonarjs/no-reference-error -- required for testing */
-/* eslint-disable es/no-legacy-object-prototype-accessor-methods -- required for testing */
-var IS_PURE = __webpack_require__(48);
-var globalThis = __webpack_require__(35);
-var fails = __webpack_require__(33);
-var WEBKIT = __webpack_require__(183);
+var getBuiltIn = __webpack_require__(11);
+var uncurryThis = __webpack_require__(2);
+var getOwnPropertyNamesModule = __webpack_require__(75);
+var getOwnPropertySymbolsModule = __webpack_require__(125);
+var anObject = __webpack_require__(5);
-// Forced replacement object prototype accessors methods
-module.exports = IS_PURE || !fails(function () {
- // This feature detection crashes old WebKit
- // https://github.com/zloirock/core-js/issues/232
- if (WEBKIT && WEBKIT < 535) return;
- var key = Math.random();
- // In FF throws only define methods
- __defineSetter__.call(null, key, function () { /* empty */ });
- delete globalThis[key];
-});
+var concat = uncurryThis([].concat);
+
+// all object keys, includes non-enumerable and symbols
+module.exports = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {
+ var keys = getOwnPropertyNamesModule.f(anObject(it));
+ var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
+ return getOwnPropertySymbols ? concat(keys, getOwnPropertySymbols(it)) : keys;
+};
/***/ }),
-/* 158 */
+/* 169 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
+/* eslint-disable regexp/no-empty-capturing-group, regexp/no-empty-group, regexp/no-lazy-ends -- testing */
+/* eslint-disable regexp/no-useless-quantifier -- testing */
+var call = __webpack_require__(4);
+var uncurryThis = __webpack_require__(2);
+var toString = __webpack_require__(9);
+var regexpFlags = __webpack_require__(170);
+var stickyHelpers = __webpack_require__(130);
+var shared = __webpack_require__(92);
+var create = __webpack_require__(30);
+var getInternalState = __webpack_require__(21).get;
+var UNSUPPORTED_DOT_ALL = __webpack_require__(171);
+var UNSUPPORTED_NCG = __webpack_require__(238);
+
+var nativeReplace = shared('native-string-replace', String.prototype.replace);
+var nativeExec = RegExp.prototype.exec;
+var patchedExec = nativeExec;
+var charAt = uncurryThis(''.charAt);
+var indexOf = uncurryThis(''.indexOf);
+var replace = uncurryThis(''.replace);
+var stringSlice = uncurryThis(''.slice);
+
+var UPDATES_LAST_INDEX_WRONG = (function () {
+ var re1 = /a/;
+ var re2 = /b*/g;
+ call(nativeExec, re1, 'a');
+ call(nativeExec, re2, 'a');
+ return re1.lastIndex !== 0 || re2.lastIndex !== 0;
+})();
+
+var UNSUPPORTED_Y = stickyHelpers.BROKEN_CARET;
+
+// nonparticipating capturing group, copied from es5-shim's String#split patch.
+var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;
+
+var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y || UNSUPPORTED_DOT_ALL || UNSUPPORTED_NCG;
+
+if (PATCH) {
+ patchedExec = function exec(string) {
+ var re = this;
+ var state = getInternalState(re);
+ var str = toString(string);
+ var raw = state.raw;
+ var result, reCopy, lastIndex, match, i, object, group;
+
+ if (raw) {
+ raw.lastIndex = re.lastIndex;
+ result = call(patchedExec, raw, str);
+ re.lastIndex = raw.lastIndex;
+ return result;
+ }
+
+ var groups = state.groups;
+ var sticky = UNSUPPORTED_Y && re.sticky;
+ var flags = call(regexpFlags, re);
+ var source = re.source;
+ var charsAdded = 0;
+ var strCopy = str;
+
+ if (sticky) {
+ flags = replace(flags, 'y', '');
+ if (indexOf(flags, 'g') === -1) {
+ flags += 'g';
+ }
+
+ strCopy = stringSlice(str, re.lastIndex);
+ // Support anchored sticky behavior.
+ if (re.lastIndex > 0 && (!re.multiline || re.multiline && charAt(str, re.lastIndex - 1) !== '\n')) {
+ source = '(?: ' + source + ')';
+ strCopy = ' ' + strCopy;
+ charsAdded++;
+ }
+ // ^(? + rx + ) is needed, in combination with some str slicing, to
+ // simulate the 'y' flag.
+ reCopy = new RegExp('^(?:' + source + ')', flags);
+ }
+
+ if (NPCG_INCLUDED) {
+ reCopy = new RegExp('^' + source + '$(?!\\s)', flags);
+ }
+ if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex;
+
+ match = call(nativeExec, sticky ? reCopy : re, strCopy);
+
+ if (sticky) {
+ if (match) {
+ match.input = stringSlice(match.input, charsAdded);
+ match[0] = stringSlice(match[0], charsAdded);
+ match.index = re.lastIndex;
+ re.lastIndex += match[0].length;
+ } else re.lastIndex = 0;
+ } else if (UPDATES_LAST_INDEX_WRONG && match) {
+ re.lastIndex = re.global ? match.index + match[0].length : lastIndex;
+ }
+ if (NPCG_INCLUDED && match && match.length > 1) {
+ // Fix browsers whose `exec` methods don't consistently return `undefined`
+ // for NPCG, like IE8. NOTE: This doesn't work for /(.?)?/
+ call(nativeReplace, match[0], reCopy, function () {
+ for (i = 1; i < arguments.length - 2; i++) {
+ if (arguments[i] === undefined) match[i] = undefined;
+ }
+ });
+ }
+
+ if (match && groups) {
+ match.groups = object = create(null);
+ for (i = 0; i < groups.length; i++) {
+ group = groups[i];
+ object[group[0]] = match[group[1]];
+ }
+ }
+
+ return match;
+ };
+}
-module.exports = globalThis;
+module.exports = patchedExec;
/***/ }),
-/* 159 */
+/* 170 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var NativePromiseConstructor = __webpack_require__(120);
-var checkCorrectnessOfIteration = __webpack_require__(145);
-var FORCED_PROMISE_CONSTRUCTOR = __webpack_require__(135).CONSTRUCTOR;
+var anObject = __webpack_require__(5);
-module.exports = FORCED_PROMISE_CONSTRUCTOR || !checkCorrectnessOfIteration(function (iterable) {
- NativePromiseConstructor.all(iterable).then(undefined, function () { /* empty */ });
-});
+// `RegExp.prototype.flags` getter implementation
+// https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
+module.exports = function () {
+ var that = anObject(this);
+ var result = '';
+ if (that.hasIndices) result += 'd';
+ if (that.global) result += 'g';
+ if (that.ignoreCase) result += 'i';
+ if (that.multiline) result += 'm';
+ if (that.dotAll) result += 's';
+ if (that.unicode) result += 'u';
+ if (that.unicodeSets) result += 'v';
+ if (that.sticky) result += 'y';
+ return result;
+};
/***/ }),
-/* 160 */
+/* 171 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var fails = __webpack_require__(33);
-var globalThis = __webpack_require__(35);
+var fails = __webpack_require__(1);
+var globalThis = __webpack_require__(3);
-// babel-minify and Closure Compiler transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError
+// babel-minify and Closure Compiler transpiles RegExp('.', 's') -> /./s and it causes SyntaxError
var $RegExp = globalThis.RegExp;
-var UNSUPPORTED_Y = fails(function () {
- var re = $RegExp('a', 'y');
- re.lastIndex = 2;
- return re.exec('abcd') !== null;
-});
-
-// UC Browser bug
-// https://github.com/zloirock/core-js/issues/1008
-var MISSED_STICKY = UNSUPPORTED_Y || fails(function () {
- return !$RegExp('a', 'y').sticky;
-});
-
-var BROKEN_CARET = UNSUPPORTED_Y || fails(function () {
- // https://bugzilla.mozilla.org/show_bug.cgi?id=773687
- var re = $RegExp('^r', 'gy');
- re.lastIndex = 2;
- return re.exec('str') !== null;
+module.exports = fails(function () {
+ var re = $RegExp('.', 's');
+ return !(re.dotAll && re.test('\n') && re.flags === 's');
});
-module.exports = {
- BROKEN_CARET: BROKEN_CARET,
- MISSED_STICKY: MISSED_STICKY,
- UNSUPPORTED_Y: UNSUPPORTED_Y
-};
-
/***/ }),
-/* 161 */
+/* 172 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var shared = __webpack_require__(123);
-var uid = __webpack_require__(126);
+var globalThis = __webpack_require__(3);
+var apply = __webpack_require__(42);
+var isCallable = __webpack_require__(14);
+var ENVIRONMENT = __webpack_require__(119);
+var USER_AGENT = __webpack_require__(51);
+var arraySlice = __webpack_require__(46);
+var validateArgumentsLength = __webpack_require__(48);
-var keys = shared('keys');
+var Function = globalThis.Function;
+// dirty IE9- and Bun 0.3.0- checks
+var WRAP = /MSIE .\./.test(USER_AGENT) || ENVIRONMENT === 'BUN' && (function () {
+ var version = globalThis.Bun.version.split('.');
+ return version.length < 3 || version[0] === '0' && (version[1] < 3 || version[1] === '3' && version[2] === '0');
+})();
-module.exports = function (key) {
- return keys[key] || (keys[key] = uid(key));
+// IE9- / Bun 0.3.0- setTimeout / setInterval / setImmediate additional parameters fix
+// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
+// https://github.com/oven-sh/bun/issues/1633
+module.exports = function (scheduler, hasTimeArg) {
+ var firstParamIndex = hasTimeArg ? 2 : 1;
+ return WRAP ? function (handler, timeout /* , ...arguments */) {
+ var boundArgs = validateArgumentsLength(arguments.length, 1) > firstParamIndex;
+ var fn = isCallable(handler) ? handler : Function(handler);
+ var params = boundArgs ? arraySlice(arguments, firstParamIndex) : [];
+ var callback = boundArgs ? function () {
+ apply(fn, this, params);
+ } : fn;
+ return hasTimeArg ? scheduler(callback, timeout) : scheduler(callback);
+ } : scheduler;
};
/***/ }),
-/* 162 */
+/* 173 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var IS_PURE = __webpack_require__(48);
-var globalThis = __webpack_require__(35);
-var defineGlobalProperty = __webpack_require__(181);
+var SetHelpers = __webpack_require__(50);
+var iterate = __webpack_require__(90);
-var SHARED = '__core-js_shared__';
-var store = module.exports = globalThis[SHARED] || defineGlobalProperty(SHARED, {});
+var Set = SetHelpers.Set;
+var add = SetHelpers.add;
-(store.versions || (store.versions = [])).push({
- version: '3.43.0',
- mode: IS_PURE ? 'pure' : 'global',
- copyright: '© 2014-2025 Denis Pushkarev (zloirock.ru)',
- license: 'https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE',
- source: 'https://github.com/zloirock/core-js'
-});
+module.exports = function (set) {
+ var result = new Set();
+ iterate(set, function (it) {
+ add(result, it);
+ });
+ return result;
+};
/***/ }),
-/* 163 */
+/* 174 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var anObject = __webpack_require__(37);
-var aConstructor = __webpack_require__(173);
-var isNullOrUndefined = __webpack_require__(89);
-var wellKnownSymbol = __webpack_require__(39);
+var PROPER_FUNCTION_NAME = __webpack_require__(82).PROPER;
+var fails = __webpack_require__(1);
+var whitespaces = __webpack_require__(107);
-var SPECIES = wellKnownSymbol('species');
+var non = '\u200B\u0085\u180E';
-// `SpeciesConstructor` abstract operation
-// https://tc39.es/ecma262/#sec-speciesconstructor
-module.exports = function (O, defaultConstructor) {
- var C = anObject(O).constructor;
- var S;
- return C === undefined || isNullOrUndefined(S = anObject(C)[SPECIES]) ? defaultConstructor : aConstructor(S);
+// check that a method works with the correct list
+// of whitespaces and has a correct name
+module.exports = function (METHOD_NAME) {
+ return fails(function () {
+ return !!whitespaces[METHOD_NAME]()
+ || non[METHOD_NAME]() !== non
+ || (PROPER_FUNCTION_NAME && whitespaces[METHOD_NAME].name !== METHOD_NAME);
+ });
};
/***/ }),
-/* 164 */
+/* 175 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
-var toIntegerOrInfinity = __webpack_require__(54);
-var toString = __webpack_require__(41);
-var requireObjectCoercible = __webpack_require__(52);
-
-var charAt = uncurryThis(''.charAt);
-var charCodeAt = uncurryThis(''.charCodeAt);
-var stringSlice = uncurryThis(''.slice);
+var globalThis = __webpack_require__(3);
+var fails = __webpack_require__(1);
+var V8 = __webpack_require__(52);
+var ENVIRONMENT = __webpack_require__(119);
-var createMethod = function (CONVERT_TO_STRING) {
- return function ($this, pos) {
- var S = toString(requireObjectCoercible($this));
- var position = toIntegerOrInfinity(pos);
- var size = S.length;
- var first, second;
- if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
- first = charCodeAt(S, position);
- return first < 0xD800 || first > 0xDBFF || position + 1 === size
- || (second = charCodeAt(S, position + 1)) < 0xDC00 || second > 0xDFFF
- ? CONVERT_TO_STRING
- ? charAt(S, position)
- : first
- : CONVERT_TO_STRING
- ? stringSlice(S, position, position + 2)
- : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
- };
-};
+var structuredClone = globalThis.structuredClone;
-module.exports = {
- // `String.prototype.codePointAt` method
- // https://tc39.es/ecma262/#sec-string.prototype.codepointat
- codeAt: createMethod(false),
- // `String.prototype.at` method
- // https://github.com/mathiasbynens/String.prototype.at
- charAt: createMethod(true)
-};
+module.exports = !!structuredClone && !fails(function () {
+ // prevent V8 ArrayBufferDetaching protector cell invalidation and performance degradation
+ // https://github.com/zloirock/core-js/issues/679
+ if ((ENVIRONMENT === 'DENO' && V8 > 92) || (ENVIRONMENT === 'NODE' && V8 > 94) || (ENVIRONMENT === 'BROWSER' && V8 > 97)) return false;
+ var buffer = new ArrayBuffer(8);
+ var clone = structuredClone(buffer, { transfer: [buffer] });
+ return buffer.byteLength !== 0 || clone.byteLength !== 8;
+});
/***/ }),
-/* 165 */
+/* 176 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-// https://github.com/tc39/proposal-string-pad-start-end
-var uncurryThis = __webpack_require__(34);
-var toLength = __webpack_require__(77);
-var toString = __webpack_require__(41);
-var $repeat = __webpack_require__(166);
-var requireObjectCoercible = __webpack_require__(52);
-
-var repeat = uncurryThis($repeat);
-var stringSlice = uncurryThis(''.slice);
-var ceil = Math.ceil;
+var toPrimitive = __webpack_require__(140);
-// `String.prototype.{ padStart, padEnd }` methods implementation
-var createMethod = function (IS_END) {
- return function ($this, maxLength, fillString) {
- var S = toString(requireObjectCoercible($this));
- var intMaxLength = toLength(maxLength);
- var stringLength = S.length;
- var fillStr = fillString === undefined ? ' ' : toString(fillString);
- var fillLen, stringFiller;
- if (intMaxLength <= stringLength || fillStr === '') return S;
- fillLen = intMaxLength - stringLength;
- stringFiller = repeat(fillStr, ceil(fillLen / fillStr.length));
- if (stringFiller.length > fillLen) stringFiller = stringSlice(stringFiller, 0, fillLen);
- return IS_END ? S + stringFiller : stringFiller + S;
- };
-};
+var $TypeError = TypeError;
-module.exports = {
- // `String.prototype.padStart` method
- // https://tc39.es/ecma262/#sec-string.prototype.padstart
- start: createMethod(false),
- // `String.prototype.padEnd` method
- // https://tc39.es/ecma262/#sec-string.prototype.padend
- end: createMethod(true)
+// `ToBigInt` abstract operation
+// https://tc39.es/ecma262/#sec-tobigint
+module.exports = function (argument) {
+ var prim = toPrimitive(argument, 'number');
+ if (typeof prim == 'number') throw new $TypeError("Can't convert number to bigint");
+ // eslint-disable-next-line es/no-bigint -- safe
+ return BigInt(prim);
};
/***/ }),
-/* 166 */
+/* 177 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var toIntegerOrInfinity = __webpack_require__(54);
-var toString = __webpack_require__(41);
-var requireObjectCoercible = __webpack_require__(52);
+var toIntegerOrInfinity = __webpack_require__(22);
var $RangeError = RangeError;
-// `String.prototype.repeat` method implementation
-// https://tc39.es/ecma262/#sec-string.prototype.repeat
-module.exports = function repeat(count) {
- var str = toString(requireObjectCoercible(this));
- var result = '';
- var n = toIntegerOrInfinity(count);
- if (n < 0 || n === Infinity) throw new $RangeError('Wrong number of repetitions');
- for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) result += str;
+module.exports = function (it) {
+ var result = toIntegerOrInfinity(it);
+ if (result < 0) throw new $RangeError("The argument can't be less than 0");
return result;
};
/***/ }),
-/* 167 */
+/* 178 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var apply = __webpack_require__(74);
-var bind = __webpack_require__(75);
-var isCallable = __webpack_require__(46);
-var hasOwn = __webpack_require__(45);
-var fails = __webpack_require__(33);
-var html = __webpack_require__(241);
-var arraySlice = __webpack_require__(78);
-var createElement = __webpack_require__(148);
-var validateArgumentsLength = __webpack_require__(80);
-var IS_IOS = __webpack_require__(232);
-var IS_NODE = __webpack_require__(111);
-
-var set = globalThis.setImmediate;
-var clear = globalThis.clearImmediate;
-var process = globalThis.process;
-var Dispatch = globalThis.Dispatch;
-var Function = globalThis.Function;
-var MessageChannel = globalThis.MessageChannel;
-var String = globalThis.String;
-var counter = 0;
-var queue = {};
-var ONREADYSTATECHANGE = 'onreadystatechange';
-var $location, defer, channel, port;
-
-fails(function () {
- // Deno throws a ReferenceError on `location` access without `--location` flag
- $location = globalThis.location;
-});
-
-var run = function (id) {
- if (hasOwn(queue, id)) {
- var fn = queue[id];
- delete queue[id];
- fn();
- }
-};
-
-var runner = function (id) {
- return function () {
- run(id);
- };
-};
-
-var eventListener = function (event) {
- run(event.data);
-};
+var wellKnownSymbol = __webpack_require__(7);
-var globalPostMessageDefer = function (id) {
- // old engines have not location.origin
- globalThis.postMessage(String(id), $location.protocol + '//' + $location.host);
-};
+var TO_STRING_TAG = wellKnownSymbol('toStringTag');
+var test = {};
-// Node.js 0.9+ & IE10+ has setImmediate, otherwise:
-if (!set || !clear) {
- set = function setImmediate(handler) {
- validateArgumentsLength(arguments.length, 1);
- var fn = isCallable(handler) ? handler : Function(handler);
- var args = arraySlice(arguments, 1);
- queue[++counter] = function () {
- apply(fn, undefined, args);
- };
- defer(counter);
- return counter;
- };
- clear = function clearImmediate(id) {
- delete queue[id];
- };
- // Node.js 0.8-
- if (IS_NODE) {
- defer = function (id) {
- process.nextTick(runner(id));
- };
- // Sphere (JS game engine) Dispatch API
- } else if (Dispatch && Dispatch.now) {
- defer = function (id) {
- Dispatch.now(runner(id));
- };
- // Browsers with MessageChannel, includes WebWorkers
- // except iOS - https://github.com/zloirock/core-js/issues/624
- } else if (MessageChannel && !IS_IOS) {
- channel = new MessageChannel();
- port = channel.port2;
- channel.port1.onmessage = eventListener;
- defer = bind(port.postMessage, port);
- // Browsers with postMessage, skip WebWorkers
- // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
- } else if (
- globalThis.addEventListener &&
- isCallable(globalThis.postMessage) &&
- !globalThis.importScripts &&
- $location && $location.protocol !== 'file:' &&
- !fails(globalPostMessageDefer)
- ) {
- defer = globalPostMessageDefer;
- globalThis.addEventListener('message', eventListener, false);
- // IE8-
- } else if (ONREADYSTATECHANGE in createElement('script')) {
- defer = function (id) {
- html.appendChild(createElement('script'))[ONREADYSTATECHANGE] = function () {
- html.removeChild(this);
- run(id);
- };
- };
- // Rest old browsers
- } else {
- defer = function (id) {
- setTimeout(runner(id), 0);
- };
- }
-}
+test[TO_STRING_TAG] = 'z';
-module.exports = {
- set: set,
- clear: clear
-};
+module.exports = String(test) === '[object z]';
/***/ }),
-/* 168 */
+/* 179 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
+/* eslint-disable no-new, sonarjs/inconsistent-function-call -- required for testing */
+var globalThis = __webpack_require__(3);
+var fails = __webpack_require__(1);
+var checkCorrectnessOfIteration = __webpack_require__(115);
+var NATIVE_ARRAY_BUFFER_VIEWS = __webpack_require__(12).NATIVE_ARRAY_BUFFER_VIEWS;
-// `thisNumberValue` abstract operation
-// https://tc39.es/ecma262/#sec-thisnumbervalue
-module.exports = uncurryThis(1.1.valueOf);
+var ArrayBuffer = globalThis.ArrayBuffer;
+var Int8Array = globalThis.Int8Array;
+
+module.exports = !NATIVE_ARRAY_BUFFER_VIEWS || !fails(function () {
+ Int8Array(1);
+}) || !fails(function () {
+ new Int8Array(-1);
+}) || !checkCorrectnessOfIteration(function (iterable) {
+ new Int8Array();
+ new Int8Array(null);
+ new Int8Array(1.5);
+ new Int8Array(iterable);
+}, true) || fails(function () {
+ // Safari (11+) bug - a reason why even Safari 13 should load a typed array polyfill
+ return new Int8Array(new ArrayBuffer(2), 1, undefined).length !== 1;
+});
/***/ }),
-/* 169 */
+/* 180 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var toIntegerOrInfinity = __webpack_require__(54);
-var toLength = __webpack_require__(77);
-
-var $RangeError = RangeError;
+var $ = __webpack_require__(0);
+var exec = __webpack_require__(169);
-// `ToIndex` abstract operation
-// https://tc39.es/ecma262/#sec-toindex
-module.exports = function (it) {
- if (it === undefined) return 0;
- var number = toIntegerOrInfinity(it);
- var length = toLength(number);
- if (number !== length) throw new $RangeError('Wrong length or index');
- return length;
-};
+// `RegExp.prototype.exec` method
+// https://tc39.es/ecma262/#sec-regexp.prototype.exec
+$({ target: 'RegExp', proto: true, forced: /./.exec !== exec }, {
+ exec: exec
+});
/***/ }),
-/* 170 */
+/* 181 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var call = __webpack_require__(36);
-var isObject = __webpack_require__(40);
-var isSymbol = __webpack_require__(104);
-var getMethod = __webpack_require__(60);
-var ordinaryToPrimitive = __webpack_require__(262);
-var wellKnownSymbol = __webpack_require__(39);
+var isPossiblePrototype = __webpack_require__(217);
+var $String = String;
var $TypeError = TypeError;
-var TO_PRIMITIVE = wellKnownSymbol('toPrimitive');
-// `ToPrimitive` abstract operation
-// https://tc39.es/ecma262/#sec-toprimitive
-module.exports = function (input, pref) {
- if (!isObject(input) || isSymbol(input)) return input;
- var exoticToPrim = getMethod(input, TO_PRIMITIVE);
- var result;
- if (exoticToPrim) {
- if (pref === undefined) pref = 'default';
- result = call(exoticToPrim, input, pref);
- if (!isObject(result) || isSymbol(result)) return result;
- throw new $TypeError("Can't convert object to primitive value");
- }
- if (pref === undefined) pref = 'number';
- return ordinaryToPrimitive(input, pref);
+module.exports = function (argument) {
+ if (isPossiblePrototype(argument)) return argument;
+ throw new $TypeError("Can't set " + $String(argument) + ' as a prototype');
};
/***/ }),
-/* 171 */
+/* 182 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var fails = __webpack_require__(33);
-var wellKnownSymbol = __webpack_require__(39);
-var DESCRIPTORS = __webpack_require__(38);
-var IS_PURE = __webpack_require__(48);
+var getBuiltIn = __webpack_require__(11);
+var call = __webpack_require__(4);
+var uncurryThis = __webpack_require__(2);
+var bind = __webpack_require__(43);
+var anObject = __webpack_require__(5);
+var aCallable = __webpack_require__(10);
+var isNullOrUndefined = __webpack_require__(57);
+var getMethod = __webpack_require__(28);
+var wellKnownSymbol = __webpack_require__(7);
-var ITERATOR = wellKnownSymbol('iterator');
+var ASYNC_DISPOSE = wellKnownSymbol('asyncDispose');
+var DISPOSE = wellKnownSymbol('dispose');
-module.exports = !fails(function () {
- // eslint-disable-next-line unicorn/relative-url-style -- required for testing
- var url = new URL('b?a=1&b=2&c=3', 'https://a');
- var params = url.searchParams;
- var params2 = new URLSearchParams('a=1&a=2&b=3');
- var result = '';
- url.pathname = 'c%20d';
- params.forEach(function (value, key) {
- params['delete']('b');
- result += key + value;
- });
- params2['delete']('a', 2);
- // `undefined` case is a Chromium 117 bug
- // https://bugs.chromium.org/p/v8/issues/detail?id=14222
- params2['delete']('b', undefined);
- return (IS_PURE && (!url.toJSON || !params2.has('a', 1) || params2.has('a', 2) || !params2.has('a', undefined) || params2.has('b')))
- || (!params.size && (IS_PURE || !DESCRIPTORS))
- || !params.sort
- || url.href !== 'https://a/c%20d?a=1&c=3'
- || params.get('c') !== '3'
- || String(new URLSearchParams('?a=1')) !== 'a=1'
- || !params[ITERATOR]
- // throws in Edge
- || new URL('https://a@b').username !== 'a'
- || new URLSearchParams(new URLSearchParams('a=b')).get('a') !== 'b'
- // not punycoded in Edge
- || new URL('https://тест').host !== 'xn--e1aybc'
- // not escaped in Chrome 62-
- || new URL('https://a#б').hash !== '#%D0%B1'
- // fails in Chrome 66-
- || result !== 'a1c3'
- // throws in Safari
- || new URL('https://x', undefined).host !== 'x';
-});
+var push = uncurryThis([].push);
+
+// `GetDisposeMethod` abstract operation
+// https://tc39.es/proposal-explicit-resource-management/#sec-getdisposemethod
+var getDisposeMethod = function (V, hint) {
+ if (hint === 'async-dispose') {
+ var method = getMethod(V, ASYNC_DISPOSE);
+ if (method !== undefined) return method;
+ method = getMethod(V, DISPOSE);
+ if (method === undefined) return method;
+ return function () {
+ var O = this;
+ var Promise = getBuiltIn('Promise');
+ return new Promise(function (resolve) {
+ call(method, O);
+ resolve(undefined);
+ });
+ };
+ } return getMethod(V, DISPOSE);
+};
+// `CreateDisposableResource` abstract operation
+// https://tc39.es/proposal-explicit-resource-management/#sec-createdisposableresource
+var createDisposableResource = function (V, hint, method) {
+ if (arguments.length < 3 && !isNullOrUndefined(V)) {
+ method = aCallable(getDisposeMethod(anObject(V), hint));
+ }
-/***/ }),
-/* 172 */
-/***/ (function(module, exports, __webpack_require__) {
+ return method === undefined ? function () {
+ return undefined;
+ } : bind(method, V);
+};
-"use strict";
+// `AddDisposableResource` abstract operation
+// https://tc39.es/proposal-explicit-resource-management/#sec-adddisposableresource
+module.exports = function (disposable, V, hint, method) {
+ var resource;
+ if (arguments.length < 4) {
+ // When `V`` is either `null` or `undefined` and hint is `async-dispose`,
+ // we record that the resource was evaluated to ensure we will still perform an `Await` when resources are later disposed.
+ if (isNullOrUndefined(V) && hint === 'sync-dispose') return;
+ resource = createDisposableResource(V, hint);
+ } else {
+ resource = createDisposableResource(undefined, hint, method);
+ }
-var toIndexedObject = __webpack_require__(57);
-var addToUnscopables = __webpack_require__(69);
-var Iterators = __webpack_require__(133);
-var InternalStateModule = __webpack_require__(53);
-var defineProperty = __webpack_require__(51).f;
-var defineIterator = __webpack_require__(190);
-var createIterResultObject = __webpack_require__(96);
-var IS_PURE = __webpack_require__(48);
-var DESCRIPTORS = __webpack_require__(38);
+ push(disposable.stack, resource);
+};
-var ARRAY_ITERATOR = 'Array Iterator';
-var setInternalState = InternalStateModule.set;
-var getInternalState = InternalStateModule.getterFor(ARRAY_ITERATOR);
-// `Array.prototype.entries` method
-// https://tc39.es/ecma262/#sec-array.prototype.entries
-// `Array.prototype.keys` method
-// https://tc39.es/ecma262/#sec-array.prototype.keys
-// `Array.prototype.values` method
-// https://tc39.es/ecma262/#sec-array.prototype.values
-// `Array.prototype[@@iterator]` method
-// https://tc39.es/ecma262/#sec-array.prototype-@@iterator
-// `CreateArrayIterator` internal method
-// https://tc39.es/ecma262/#sec-createarrayiterator
-module.exports = defineIterator(Array, 'Array', function (iterated, kind) {
- setInternalState(this, {
- type: ARRAY_ITERATOR,
- target: toIndexedObject(iterated), // target
- index: 0, // next index
- kind: kind // kind
- });
-// `%ArrayIteratorPrototype%.next` method
-// https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next
-}, function () {
- var state = getInternalState(this);
- var target = state.target;
- var index = state.index++;
- if (!target || index >= target.length) {
- state.target = null;
- return createIterResultObject(undefined, true);
- }
- switch (state.kind) {
- case 'keys': return createIterResultObject(index, false);
- case 'values': return createIterResultObject(target[index], false);
- } return createIterResultObject([index, target[index]], false);
-}, 'values');
+/***/ }),
+/* 183 */
+/***/ (function(module, exports, __webpack_require__) {
-// argumentsList[@@iterator] is %ArrayProto_values%
-// https://tc39.es/ecma262/#sec-createunmappedargumentsobject
-// https://tc39.es/ecma262/#sec-createmappedargumentsobject
-var values = Iterators.Arguments = Iterators.Array;
+"use strict";
-// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
-addToUnscopables('keys');
-addToUnscopables('values');
-addToUnscopables('entries');
+var globalThis = __webpack_require__(3);
+var uncurryThisAccessor = __webpack_require__(121);
+var classof = __webpack_require__(32);
-// V8 ~ Chrome 45- bug
-if (!IS_PURE && DESCRIPTORS && values.name !== 'values') try {
- defineProperty(values, 'name', { value: 'values' });
-} catch (error) { /* empty */ }
+var ArrayBuffer = globalThis.ArrayBuffer;
+var TypeError = globalThis.TypeError;
+
+// Includes
+// - Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
+// - If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
+module.exports = ArrayBuffer && uncurryThisAccessor(ArrayBuffer.prototype, 'byteLength', 'get') || function (O) {
+ if (classof(O) !== 'ArrayBuffer') throw new TypeError('ArrayBuffer expected');
+ return O.byteLength;
+};
/***/ }),
-/* 173 */
+/* 184 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isConstructor = __webpack_require__(103);
-var tryToString = __webpack_require__(109);
+var globalThis = __webpack_require__(3);
+var NATIVE_ARRAY_BUFFER = __webpack_require__(110);
+var arrayBufferByteLength = __webpack_require__(183);
-var $TypeError = TypeError;
+var DataView = globalThis.DataView;
-// `Assert: IsConstructor(argument) is true`
-module.exports = function (argument) {
- if (isConstructor(argument)) return argument;
- throw new $TypeError(tryToString(argument) + ' is not a constructor');
+module.exports = function (O) {
+ if (!NATIVE_ARRAY_BUFFER || arrayBufferByteLength(O) !== 0) return false;
+ try {
+ // eslint-disable-next-line no-new -- thrower
+ new DataView(O);
+ return false;
+ } catch (error) {
+ return true;
+ }
};
/***/ }),
-/* 174 */
+/* 185 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-// FF26- bug: ArrayBuffers are non-extensible, but Object.isExtensible does not report it
-var fails = __webpack_require__(33);
+var globalThis = __webpack_require__(3);
+var uncurryThis = __webpack_require__(2);
+var uncurryThisAccessor = __webpack_require__(121);
+var toIndex = __webpack_require__(139);
+var notDetached = __webpack_require__(284);
+var arrayBufferByteLength = __webpack_require__(183);
+var detachTransferable = __webpack_require__(197);
+var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__(175);
-module.exports = fails(function () {
- if (typeof ArrayBuffer == 'function') {
- var buffer = new ArrayBuffer(8);
- // eslint-disable-next-line es/no-object-isextensible, es/no-object-defineproperty -- safe
- if (Object.isExtensible(buffer)) Object.defineProperty(buffer, 'a', { value: 8 });
+var structuredClone = globalThis.structuredClone;
+var ArrayBuffer = globalThis.ArrayBuffer;
+var DataView = globalThis.DataView;
+var min = Math.min;
+var ArrayBufferPrototype = ArrayBuffer.prototype;
+var DataViewPrototype = DataView.prototype;
+var slice = uncurryThis(ArrayBufferPrototype.slice);
+var isResizable = uncurryThisAccessor(ArrayBufferPrototype, 'resizable', 'get');
+var maxByteLength = uncurryThisAccessor(ArrayBufferPrototype, 'maxByteLength', 'get');
+var getInt8 = uncurryThis(DataViewPrototype.getInt8);
+var setInt8 = uncurryThis(DataViewPrototype.setInt8);
+
+module.exports = (PROPER_STRUCTURED_CLONE_TRANSFER || detachTransferable) && function (arrayBuffer, newLength, preserveResizability) {
+ var byteLength = arrayBufferByteLength(arrayBuffer);
+ var newByteLength = newLength === undefined ? byteLength : toIndex(newLength);
+ var fixedLength = !isResizable || !isResizable(arrayBuffer);
+ var newBuffer;
+ notDetached(arrayBuffer);
+ if (PROPER_STRUCTURED_CLONE_TRANSFER) {
+ arrayBuffer = structuredClone(arrayBuffer, { transfer: [arrayBuffer] });
+ if (byteLength === newByteLength && (preserveResizability || fixedLength)) return arrayBuffer;
}
-});
+ if (byteLength >= newByteLength && (!preserveResizability || fixedLength)) {
+ newBuffer = slice(arrayBuffer, 0, newByteLength);
+ } else {
+ var options = preserveResizability && !fixedLength && maxByteLength ? { maxByteLength: maxByteLength(arrayBuffer) } : undefined;
+ newBuffer = new ArrayBuffer(newByteLength, options);
+ var a = new DataView(arrayBuffer);
+ var b = new DataView(newBuffer);
+ var copyLength = min(newByteLength, byteLength);
+ for (var i = 0; i < copyLength; i++) setInt8(b, i, getInt8(a, i));
+ }
+ if (!PROPER_STRUCTURED_CLONE_TRANSFER) detachTransferable(arrayBuffer);
+ return newBuffer;
+};
/***/ }),
-/* 175 */
+/* 186 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var toObject = __webpack_require__(47);
-var toAbsoluteIndex = __webpack_require__(91);
-var lengthOfArrayLike = __webpack_require__(50);
+var toObject = __webpack_require__(15);
+var toAbsoluteIndex = __webpack_require__(59);
+var lengthOfArrayLike = __webpack_require__(18);
+var deletePropertyOrThrow = __webpack_require__(117);
-// `Array.prototype.fill` method implementation
-// https://tc39.es/ecma262/#sec-array.prototype.fill
-module.exports = function fill(value /* , start = 0, end = @length */) {
+var min = Math.min;
+
+// `Array.prototype.copyWithin` method implementation
+// https://tc39.es/ecma262/#sec-array.prototype.copywithin
+// eslint-disable-next-line es/no-array-prototype-copywithin -- safe
+module.exports = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) {
var O = toObject(this);
- var length = lengthOfArrayLike(O);
- var argumentsLength = arguments.length;
- var index = toAbsoluteIndex(argumentsLength > 1 ? arguments[1] : undefined, length);
- var end = argumentsLength > 2 ? arguments[2] : undefined;
- var endPos = end === undefined ? length : toAbsoluteIndex(end, length);
- while (endPos > index) O[index++] = value;
- return O;
+ var len = lengthOfArrayLike(O);
+ var to = toAbsoluteIndex(target, len);
+ var from = toAbsoluteIndex(start, len);
+ var end = arguments.length > 2 ? arguments[2] : undefined;
+ var count = min((end === undefined ? len : toAbsoluteIndex(end, len)) - from, len - to);
+ var inc = 1;
+ if (from < to && to < from + count) {
+ inc = -1;
+ from += count - 1;
+ to += count - 1;
+ }
+ while (count-- > 0) {
+ if (from in O) O[to] = O[from];
+ else deletePropertyOrThrow(O, to);
+ to += inc;
+ from += inc;
+ } return O;
};
/***/ }),
-/* 176 */
+/* 187 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var DESCRIPTORS = __webpack_require__(38);
-var isArray = __webpack_require__(93);
-
-var $TypeError = TypeError;
-// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
-var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+var $forEach = __webpack_require__(26).forEach;
+var arrayMethodIsStrict = __webpack_require__(54);
-// Safari < 13 does not throw an error in this case
-var SILENT_ON_NON_WRITABLE_LENGTH_SET = DESCRIPTORS && !function () {
- // makes no sense without proper strict mode support
- if (this !== undefined) return true;
- try {
- // eslint-disable-next-line es/no-object-defineproperty -- safe
- Object.defineProperty([], 'length', { writable: false }).length = 1;
- } catch (error) {
- return error instanceof TypeError;
- }
-}();
+var STRICT_METHOD = arrayMethodIsStrict('forEach');
-module.exports = SILENT_ON_NON_WRITABLE_LENGTH_SET ? function (O, length) {
- if (isArray(O) && !getOwnPropertyDescriptor(O, 'length').writable) {
- throw new $TypeError('Cannot set read only .length');
- } return O.length = length;
-} : function (O, length) {
- return O.length = length;
-};
+// `Array.prototype.forEach` method implementation
+// https://tc39.es/ecma262/#sec-array.prototype.foreach
+module.exports = !STRICT_METHOD ? function forEach(callbackfn /* , thisArg */) {
+ return $forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
+// eslint-disable-next-line es/no-array-prototype-foreach -- safe
+} : [].forEach;
/***/ }),
-/* 177 */
+/* 188 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var arraySlice = __webpack_require__(78);
-
-var floor = Math.floor;
-
-var sort = function (array, comparefn) {
- var length = array.length;
+var bind = __webpack_require__(43);
+var call = __webpack_require__(4);
+var toObject = __webpack_require__(15);
+var callWithSafeIterationClosing = __webpack_require__(149);
+var isArrayIteratorMethod = __webpack_require__(158);
+var isConstructor = __webpack_require__(72);
+var lengthOfArrayLike = __webpack_require__(18);
+var createProperty = __webpack_require__(55);
+var getIterator = __webpack_require__(83);
+var getIteratorMethod = __webpack_require__(68);
- if (length < 8) {
- // insertion sort
- var i = 1;
- var element, j;
+var $Array = Array;
- while (i < length) {
- j = i;
- element = array[i];
- while (j && comparefn(array[j - 1], element) > 0) {
- array[j] = array[--j];
- }
- if (j !== i++) array[j] = element;
+// `Array.from` method implementation
+// https://tc39.es/ecma262/#sec-array.from
+module.exports = function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
+ var O = toObject(arrayLike);
+ var IS_CONSTRUCTOR = isConstructor(this);
+ var argumentsLength = arguments.length;
+ var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
+ var mapping = mapfn !== undefined;
+ if (mapping) mapfn = bind(mapfn, argumentsLength > 2 ? arguments[2] : undefined);
+ var iteratorMethod = getIteratorMethod(O);
+ var index = 0;
+ var length, result, step, iterator, next, value;
+ // if the target is not iterable or it's an array with the default iterator - use a simple case
+ if (iteratorMethod && !(this === $Array && isArrayIteratorMethod(iteratorMethod))) {
+ result = IS_CONSTRUCTOR ? new this() : [];
+ iterator = getIterator(O, iteratorMethod);
+ next = iterator.next;
+ for (;!(step = call(next, iterator)).done; index++) {
+ value = mapping ? callWithSafeIterationClosing(iterator, mapfn, [step.value, index], true) : step.value;
+ createProperty(result, index, value);
}
} else {
- // merge sort
- var middle = floor(length / 2);
- var left = sort(arraySlice(array, 0, middle), comparefn);
- var right = sort(arraySlice(array, middle), comparefn);
- var llength = left.length;
- var rlength = right.length;
- var lindex = 0;
- var rindex = 0;
-
- while (lindex < llength || rindex < rlength) {
- array[lindex + rindex] = (lindex < llength && rindex < rlength)
- ? comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++]
- : lindex < llength ? left[lindex++] : right[rindex++];
+ length = lengthOfArrayLike(O);
+ result = IS_CONSTRUCTOR ? new this(length) : $Array(length);
+ for (;length > index; index++) {
+ value = mapping ? mapfn(O[index], index) : O[index];
+ createProperty(result, index, value);
}
}
-
- return array;
+ result.length = index;
+ return result;
};
-module.exports = sort;
-
/***/ }),
-/* 178 */
+/* 189 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var anObject = __webpack_require__(37);
-var iteratorClose = __webpack_require__(61);
+/* eslint-disable es/no-array-prototype-lastindexof -- safe */
+var apply = __webpack_require__(42);
+var toIndexedObject = __webpack_require__(25);
+var toIntegerOrInfinity = __webpack_require__(22);
+var lengthOfArrayLike = __webpack_require__(18);
+var arrayMethodIsStrict = __webpack_require__(54);
-// call something on iterator step with safe closing on error
-module.exports = function (iterator, fn, value, ENTRIES) {
- try {
- return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value);
- } catch (error) {
- iteratorClose(iterator, 'throw', error);
- }
-};
+var min = Math.min;
+var $lastIndexOf = [].lastIndexOf;
+var NEGATIVE_ZERO = !!$lastIndexOf && 1 / [1].lastIndexOf(1, -0) < 0;
+var STRICT_METHOD = arrayMethodIsStrict('lastIndexOf');
+var FORCED = NEGATIVE_ZERO || !STRICT_METHOD;
+
+// `Array.prototype.lastIndexOf` method implementation
+// https://tc39.es/ecma262/#sec-array.prototype.lastindexof
+module.exports = FORCED ? function lastIndexOf(searchElement /* , fromIndex = @[*-1] */) {
+ // convert -0 to +0
+ if (NEGATIVE_ZERO) return apply($lastIndexOf, this, arguments) || 0;
+ var O = toIndexedObject(this);
+ var length = lengthOfArrayLike(O);
+ if (length === 0) return -1;
+ var index = length - 1;
+ if (arguments.length > 1) index = min(index, toIntegerOrInfinity(arguments[1]));
+ if (index < 0) index = length + index;
+ for (;index >= 0; index--) if (index in O && O[index] === searchElement) return index || 0;
+ return -1;
+} : $lastIndexOf;
/***/ }),
-/* 179 */
+/* 190 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var wellKnownSymbol = __webpack_require__(39);
+var lengthOfArrayLike = __webpack_require__(18);
-var MATCH = wellKnownSymbol('match');
-
-module.exports = function (METHOD_NAME) {
- var regexp = /./;
- try {
- '/./'[METHOD_NAME](regexp);
- } catch (error1) {
- try {
- regexp[MATCH] = false;
- return '/./'[METHOD_NAME](regexp);
- } catch (error2) { /* empty */ }
- } return false;
+// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toReversed
+// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toReversed
+module.exports = function (O, C) {
+ var len = lengthOfArrayLike(O);
+ var A = new C(len);
+ var k = 0;
+ for (; k < len; k++) A[k] = O[len - k - 1];
+ return A;
};
/***/ }),
-/* 180 */
+/* 191 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var fails = __webpack_require__(33);
+var lengthOfArrayLike = __webpack_require__(18);
+var toIntegerOrInfinity = __webpack_require__(22);
-module.exports = !fails(function () {
- function F() { /* empty */ }
- F.prototype.constructor = null;
- // eslint-disable-next-line es/no-object-getprototypeof -- required for testing
- return Object.getPrototypeOf(new F()) !== F.prototype;
-});
+var $RangeError = RangeError;
+
+// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.with
+// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.with
+module.exports = function (O, C, index, value) {
+ var len = lengthOfArrayLike(O);
+ var relativeIndex = toIntegerOrInfinity(index);
+ var actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex;
+ if (actualIndex >= len || actualIndex < 0) throw new $RangeError('Incorrect index');
+ var A = new C(len);
+ var k = 0;
+ for (; k < len; k++) A[k] = k === actualIndex ? value : O[k];
+ return A;
+};
/***/ }),
-/* 181 */
+/* 192 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
+var call = __webpack_require__(4);
+var anObject = __webpack_require__(5);
+var create = __webpack_require__(30);
+var getMethod = __webpack_require__(28);
+var defineBuiltIns = __webpack_require__(56);
+var InternalStateModule = __webpack_require__(21);
+var iteratorClose = __webpack_require__(29);
+var getBuiltIn = __webpack_require__(11);
+var AsyncIteratorPrototype = __webpack_require__(193);
+var createIterResultObject = __webpack_require__(65);
-// eslint-disable-next-line es/no-object-defineproperty -- safe
-var defineProperty = Object.defineProperty;
+var Promise = getBuiltIn('Promise');
-module.exports = function (key, value) {
- try {
- defineProperty(globalThis, key, { value: value, configurable: true, writable: true });
- } catch (error) {
- globalThis[key] = value;
- } return value;
+var ASYNC_FROM_SYNC_ITERATOR = 'AsyncFromSyncIterator';
+var setInternalState = InternalStateModule.set;
+var getInternalState = InternalStateModule.getterFor(ASYNC_FROM_SYNC_ITERATOR);
+
+var asyncFromSyncIteratorContinuation = function (result, resolve, reject, syncIterator, closeOnRejection) {
+ var done = result.done;
+ Promise.resolve(result.value).then(function (value) {
+ resolve(createIterResultObject(value, done));
+ }, function (error) {
+ if (!done && closeOnRejection) {
+ try {
+ iteratorClose(syncIterator, 'throw', error);
+ } catch (error2) {
+ error = error2;
+ }
+ }
+
+ reject(error);
+ });
};
+var AsyncFromSyncIterator = function AsyncIterator(iteratorRecord) {
+ iteratorRecord.type = ASYNC_FROM_SYNC_ITERATOR;
+ setInternalState(this, iteratorRecord);
+};
+
+AsyncFromSyncIterator.prototype = defineBuiltIns(create(AsyncIteratorPrototype), {
+ next: function next() {
+ var state = getInternalState(this);
+ return new Promise(function (resolve, reject) {
+ var result = anObject(call(state.next, state.iterator));
+ asyncFromSyncIteratorContinuation(result, resolve, reject, state.iterator, true);
+ });
+ },
+ 'return': function () {
+ var iterator = getInternalState(this).iterator;
+ return new Promise(function (resolve, reject) {
+ var $return = getMethod(iterator, 'return');
+ if ($return === undefined) return resolve(createIterResultObject(undefined, true));
+ var result = anObject(call($return, iterator));
+ asyncFromSyncIteratorContinuation(result, resolve, reject, iterator);
+ });
+ }
+});
+
+module.exports = AsyncFromSyncIterator;
+
/***/ }),
-/* 182 */
+/* 193 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-// IE8- don't enum bug keys
-module.exports = [
- 'constructor',
- 'hasOwnProperty',
- 'isPrototypeOf',
- 'propertyIsEnumerable',
- 'toLocaleString',
- 'toString',
- 'valueOf'
-];
+var globalThis = __webpack_require__(3);
+var shared = __webpack_require__(132);
+var isCallable = __webpack_require__(14);
+var create = __webpack_require__(30);
+var getPrototypeOf = __webpack_require__(35);
+var defineBuiltIn = __webpack_require__(17);
+var wellKnownSymbol = __webpack_require__(7);
+var IS_PURE = __webpack_require__(16);
+
+var USE_FUNCTION_CONSTRUCTOR = 'USE_FUNCTION_CONSTRUCTOR';
+var ASYNC_ITERATOR = wellKnownSymbol('asyncIterator');
+var AsyncIterator = globalThis.AsyncIterator;
+var PassedAsyncIteratorPrototype = shared.AsyncIteratorPrototype;
+var AsyncIteratorPrototype, prototype;
+
+if (PassedAsyncIteratorPrototype) {
+ AsyncIteratorPrototype = PassedAsyncIteratorPrototype;
+} else if (isCallable(AsyncIterator)) {
+ AsyncIteratorPrototype = AsyncIterator.prototype;
+} else if (shared[USE_FUNCTION_CONSTRUCTOR] || globalThis[USE_FUNCTION_CONSTRUCTOR]) {
+ try {
+ // eslint-disable-next-line no-new-func -- we have no alternatives without usage of modern syntax
+ prototype = getPrototypeOf(getPrototypeOf(getPrototypeOf(Function('return async function*(){}()')())));
+ if (getPrototypeOf(prototype) === Object.prototype) AsyncIteratorPrototype = prototype;
+ } catch (error) { /* empty */ }
+}
+
+if (!AsyncIteratorPrototype) AsyncIteratorPrototype = {};
+else if (IS_PURE) AsyncIteratorPrototype = create(AsyncIteratorPrototype);
+
+if (!isCallable(AsyncIteratorPrototype[ASYNC_ITERATOR])) {
+ defineBuiltIn(AsyncIteratorPrototype, ASYNC_ITERATOR, function () {
+ return this;
+ });
+}
+
+module.exports = AsyncIteratorPrototype;
/***/ }),
-/* 183 */
+/* 194 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var userAgent = __webpack_require__(83);
+var commonAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+var base64Alphabet = commonAlphabet + '+/';
+var base64UrlAlphabet = commonAlphabet + '-_';
-var webkit = userAgent.match(/AppleWebKit\/(\d+)\./);
+var inverse = function (characters) {
+ // TODO: use `Object.create(null)` in `core-js@4`
+ var result = {};
+ var index = 0;
+ for (; index < 64; index++) result[characters.charAt(index)] = index;
+ return result;
+};
-module.exports = !!webkit && +webkit[1];
+module.exports = {
+ i2c: base64Alphabet,
+ c2i: inverse(base64Alphabet),
+ i2cUrl: base64UrlAlphabet,
+ c2iUrl: inverse(base64UrlAlphabet)
+};
/***/ }),
-/* 184 */
+/* 195 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
+var create = __webpack_require__(30);
+var defineBuiltInAccessor = __webpack_require__(23);
+var defineBuiltIns = __webpack_require__(56);
+var bind = __webpack_require__(43);
+var anInstance = __webpack_require__(39);
+var isNullOrUndefined = __webpack_require__(57);
+var iterate = __webpack_require__(24);
+var defineIterator = __webpack_require__(161);
+var createIterResultObject = __webpack_require__(65);
+var setSpecies = __webpack_require__(91);
+var DESCRIPTORS = __webpack_require__(6);
+var fastKey = __webpack_require__(71).fastKey;
+var InternalStateModule = __webpack_require__(21);
-var $Error = Error;
-var replace = uncurryThis(''.replace);
+var setInternalState = InternalStateModule.set;
+var internalStateGetterFor = InternalStateModule.getterFor;
-var TEST = (function (arg) { return String(new $Error(arg).stack); })('zxcasd');
-// eslint-disable-next-line redos/no-vulnerable, sonarjs/slow-regex -- safe
-var V8_OR_CHAKRA_STACK_ENTRY = /\n\s*at [^:]*:[^\n]*/;
-var IS_V8_OR_CHAKRA_STACK = V8_OR_CHAKRA_STACK_ENTRY.test(TEST);
+module.exports = {
+ getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
+ var Constructor = wrapper(function (that, iterable) {
+ anInstance(that, Prototype);
+ setInternalState(that, {
+ type: CONSTRUCTOR_NAME,
+ index: create(null),
+ first: null,
+ last: null,
+ size: 0
+ });
+ if (!DESCRIPTORS) that.size = 0;
+ if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
+ });
-module.exports = function (stack, dropEntries) {
- if (IS_V8_OR_CHAKRA_STACK && typeof stack == 'string' && !$Error.prepareStackTrace) {
- while (dropEntries--) stack = replace(stack, V8_OR_CHAKRA_STACK_ENTRY, '');
- } return stack;
-};
+ var Prototype = Constructor.prototype;
+ var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
-/***/ }),
-/* 185 */
-/***/ (function(module, exports, __webpack_require__) {
+ var define = function (that, key, value) {
+ var state = getInternalState(that);
+ var entry = getEntry(that, key);
+ var previous, index;
+ // change existing entry
+ if (entry) {
+ entry.value = value;
+ // create new entry
+ } else {
+ state.last = entry = {
+ index: index = fastKey(key, true),
+ key: key,
+ value: value,
+ previous: previous = state.last,
+ next: null,
+ removed: false
+ };
+ if (!state.first) state.first = entry;
+ if (previous) previous.next = entry;
+ if (DESCRIPTORS) state.size++;
+ else that.size++;
+ // add to index
+ if (index !== 'F') state.index[index] = entry;
+ } return that;
+ };
-"use strict";
+ var getEntry = function (that, key) {
+ var state = getInternalState(that);
+ // fast case
+ var index = fastKey(key);
+ var entry;
+ if (index !== 'F') return state.index[index];
+ // frozen object case
+ for (entry = state.first; entry; entry = entry.next) {
+ if (entry.key === key) return entry;
+ }
+ };
-var createNonEnumerableProperty = __webpack_require__(59);
-var clearErrorStack = __webpack_require__(184);
-var ERROR_STACK_INSTALLABLE = __webpack_require__(233);
+ defineBuiltIns(Prototype, {
+ // `{ Map, Set }.prototype.clear()` methods
+ // https://tc39.es/ecma262/#sec-map.prototype.clear
+ // https://tc39.es/ecma262/#sec-set.prototype.clear
+ clear: function clear() {
+ var that = this;
+ var state = getInternalState(that);
+ var entry = state.first;
+ while (entry) {
+ entry.removed = true;
+ if (entry.previous) entry.previous = entry.previous.next = null;
+ entry = entry.next;
+ }
+ state.first = state.last = null;
+ state.index = create(null);
+ if (DESCRIPTORS) state.size = 0;
+ else that.size = 0;
+ },
+ // `{ Map, Set }.prototype.delete(key)` methods
+ // https://tc39.es/ecma262/#sec-map.prototype.delete
+ // https://tc39.es/ecma262/#sec-set.prototype.delete
+ 'delete': function (key) {
+ var that = this;
+ var state = getInternalState(that);
+ var entry = getEntry(that, key);
+ if (entry) {
+ var next = entry.next;
+ var prev = entry.previous;
+ delete state.index[entry.index];
+ entry.removed = true;
+ if (prev) prev.next = next;
+ if (next) next.previous = prev;
+ if (state.first === entry) state.first = next;
+ if (state.last === entry) state.last = prev;
+ if (DESCRIPTORS) state.size--;
+ else that.size--;
+ } return !!entry;
+ },
+ // `{ Map, Set }.prototype.forEach(callbackfn, thisArg = undefined)` methods
+ // https://tc39.es/ecma262/#sec-map.prototype.foreach
+ // https://tc39.es/ecma262/#sec-set.prototype.foreach
+ forEach: function forEach(callbackfn /* , that = undefined */) {
+ var state = getInternalState(this);
+ var boundFunction = bind(callbackfn, arguments.length > 1 ? arguments[1] : undefined);
+ var entry;
+ while (entry = entry ? entry.next : state.first) {
+ boundFunction(entry.value, entry.key, this);
+ // revert to the last existing entry
+ while (entry && entry.removed) entry = entry.previous;
+ }
+ },
+ // `{ Map, Set}.prototype.has(key)` methods
+ // https://tc39.es/ecma262/#sec-map.prototype.has
+ // https://tc39.es/ecma262/#sec-set.prototype.has
+ has: function has(key) {
+ return !!getEntry(this, key);
+ }
+ });
-// non-standard V8
-// eslint-disable-next-line es/no-nonstandard-error-properties -- safe
-var captureStackTrace = Error.captureStackTrace;
+ defineBuiltIns(Prototype, IS_MAP ? {
+ // `Map.prototype.get(key)` method
+ // https://tc39.es/ecma262/#sec-map.prototype.get
+ get: function get(key) {
+ var entry = getEntry(this, key);
+ return entry && entry.value;
+ },
+ // `Map.prototype.set(key, value)` method
+ // https://tc39.es/ecma262/#sec-map.prototype.set
+ set: function set(key, value) {
+ return define(this, key === 0 ? 0 : key, value);
+ }
+ } : {
+ // `Set.prototype.add(value)` method
+ // https://tc39.es/ecma262/#sec-set.prototype.add
+ add: function add(value) {
+ return define(this, value = value === 0 ? 0 : value, value);
+ }
+ });
+ if (DESCRIPTORS) defineBuiltInAccessor(Prototype, 'size', {
+ configurable: true,
+ get: function () {
+ return getInternalState(this).size;
+ }
+ });
+ return Constructor;
+ },
+ setStrong: function (Constructor, CONSTRUCTOR_NAME, IS_MAP) {
+ var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator';
+ var getInternalCollectionState = internalStateGetterFor(CONSTRUCTOR_NAME);
+ var getInternalIteratorState = internalStateGetterFor(ITERATOR_NAME);
+ // `{ Map, Set }.prototype.{ keys, values, entries, @@iterator }()` methods
+ // https://tc39.es/ecma262/#sec-map.prototype.entries
+ // https://tc39.es/ecma262/#sec-map.prototype.keys
+ // https://tc39.es/ecma262/#sec-map.prototype.values
+ // https://tc39.es/ecma262/#sec-map.prototype-@@iterator
+ // https://tc39.es/ecma262/#sec-set.prototype.entries
+ // https://tc39.es/ecma262/#sec-set.prototype.keys
+ // https://tc39.es/ecma262/#sec-set.prototype.values
+ // https://tc39.es/ecma262/#sec-set.prototype-@@iterator
+ defineIterator(Constructor, CONSTRUCTOR_NAME, function (iterated, kind) {
+ setInternalState(this, {
+ type: ITERATOR_NAME,
+ target: iterated,
+ state: getInternalCollectionState(iterated),
+ kind: kind,
+ last: null
+ });
+ }, function () {
+ var state = getInternalIteratorState(this);
+ var kind = state.kind;
+ var entry = state.last;
+ // revert to the last existing entry
+ while (entry && entry.removed) entry = entry.previous;
+ // get next entry
+ if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) {
+ // or finish the iteration
+ state.target = null;
+ return createIterResultObject(undefined, true);
+ }
+ // return step by kind
+ if (kind === 'keys') return createIterResultObject(entry.key, false);
+ if (kind === 'values') return createIterResultObject(entry.value, false);
+ return createIterResultObject([entry.key, entry.value], false);
+ }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);
-module.exports = function (error, C, stack, dropEntries) {
- if (ERROR_STACK_INSTALLABLE) {
- if (captureStackTrace) captureStackTrace(error, C);
- else createNonEnumerableProperty(error, 'stack', clearErrorStack(stack, dropEntries));
+ // `{ Map, Set }.prototype[@@species]` accessors
+ // https://tc39.es/ecma262/#sec-get-map-@@species
+ // https://tc39.es/ecma262/#sec-get-set-@@species
+ setSpecies(CONSTRUCTOR_NAME);
}
};
/***/ }),
-/* 186 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var uncurryThis = __webpack_require__(34);
-var isCallable = __webpack_require__(46);
-var store = __webpack_require__(162);
-
-var functionToString = uncurryThis(Function.toString);
-
-// this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper
-if (!isCallable(store.inspectSource)) {
- store.inspectSource = function (it) {
- return functionToString(it);
- };
-}
-
-module.exports = store.inspectSource;
-
-
-/***/ }),
-/* 187 */
+/* 196 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var wellKnownSymbol = __webpack_require__(39);
-var Iterators = __webpack_require__(133);
+var uncurryThis = __webpack_require__(2);
+var defineBuiltIns = __webpack_require__(56);
+var getWeakData = __webpack_require__(71).getWeakData;
+var anInstance = __webpack_require__(39);
+var anObject = __webpack_require__(5);
+var isNullOrUndefined = __webpack_require__(57);
+var isObject = __webpack_require__(8);
+var iterate = __webpack_require__(24);
+var ArrayIterationModule = __webpack_require__(26);
+var hasOwn = __webpack_require__(13);
+var InternalStateModule = __webpack_require__(21);
-var ITERATOR = wellKnownSymbol('iterator');
-var ArrayPrototype = Array.prototype;
+var setInternalState = InternalStateModule.set;
+var internalStateGetterFor = InternalStateModule.getterFor;
+var find = ArrayIterationModule.find;
+var findIndex = ArrayIterationModule.findIndex;
+var splice = uncurryThis([].splice);
+var id = 0;
-// check on default Array iterator
-module.exports = function (it) {
- return it !== undefined && (Iterators.Array === it || ArrayPrototype[ITERATOR] === it);
+// fallback for uncaught frozen keys
+var uncaughtFrozenStore = function (state) {
+ return state.frozen || (state.frozen = new UncaughtFrozenStore());
};
-
-/***/ }),
-/* 188 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var isObject = __webpack_require__(40);
-
-var floor = Math.floor;
-
-// `IsIntegralNumber` abstract operation
-// https://tc39.es/ecma262/#sec-isintegralnumber
-// eslint-disable-next-line es/no-number-isinteger -- safe
-module.exports = Number.isInteger || function isInteger(it) {
- return !isObject(it) && isFinite(it) && floor(it) === it;
+var UncaughtFrozenStore = function () {
+ this.entries = [];
};
-
-/***/ }),
-/* 189 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var IteratorPrototype = __webpack_require__(117).IteratorPrototype;
-var create = __webpack_require__(62);
-var createPropertyDescriptor = __webpack_require__(73);
-var setToStringTag = __webpack_require__(70);
-var Iterators = __webpack_require__(133);
-
-var returnThis = function () { return this; };
-
-module.exports = function (IteratorConstructor, NAME, next, ENUMERABLE_NEXT) {
- var TO_STRING_TAG = NAME + ' Iterator';
- IteratorConstructor.prototype = create(IteratorPrototype, { next: createPropertyDescriptor(+!ENUMERABLE_NEXT, next) });
- setToStringTag(IteratorConstructor, TO_STRING_TAG, false, true);
- Iterators[TO_STRING_TAG] = returnThis;
- return IteratorConstructor;
+var findUncaughtFrozen = function (store, key) {
+ return find(store.entries, function (it) {
+ return it[0] === key;
+ });
};
+UncaughtFrozenStore.prototype = {
+ get: function (key) {
+ var entry = findUncaughtFrozen(this, key);
+ if (entry) return entry[1];
+ },
+ has: function (key) {
+ return !!findUncaughtFrozen(this, key);
+ },
+ set: function (key, value) {
+ var entry = findUncaughtFrozen(this, key);
+ if (entry) entry[1] = value;
+ else this.entries.push([key, value]);
+ },
+ 'delete': function (key) {
+ var index = findIndex(this.entries, function (it) {
+ return it[0] === key;
+ });
+ if (~index) splice(this.entries, index, 1);
+ return !!~index;
+ }
+};
-/***/ }),
-/* 190 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-var $ = __webpack_require__(32);
-var call = __webpack_require__(36);
-var IS_PURE = __webpack_require__(48);
-var FunctionName = __webpack_require__(113);
-var isCallable = __webpack_require__(46);
-var createIteratorConstructor = __webpack_require__(189);
-var getPrototypeOf = __webpack_require__(67);
-var setPrototypeOf = __webpack_require__(81);
-var setToStringTag = __webpack_require__(70);
-var createNonEnumerableProperty = __webpack_require__(59);
-var defineBuiltIn = __webpack_require__(49);
-var wellKnownSymbol = __webpack_require__(39);
-var Iterators = __webpack_require__(133);
-var IteratorsCore = __webpack_require__(117);
-
-var PROPER_FUNCTION_NAME = FunctionName.PROPER;
-var CONFIGURABLE_FUNCTION_NAME = FunctionName.CONFIGURABLE;
-var IteratorPrototype = IteratorsCore.IteratorPrototype;
-var BUGGY_SAFARI_ITERATORS = IteratorsCore.BUGGY_SAFARI_ITERATORS;
-var ITERATOR = wellKnownSymbol('iterator');
-var KEYS = 'keys';
-var VALUES = 'values';
-var ENTRIES = 'entries';
-
-var returnThis = function () { return this; };
-
-module.exports = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
- createIteratorConstructor(IteratorConstructor, NAME, next);
+module.exports = {
+ getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
+ var Constructor = wrapper(function (that, iterable) {
+ anInstance(that, Prototype);
+ setInternalState(that, {
+ type: CONSTRUCTOR_NAME,
+ id: id++,
+ frozen: null
+ });
+ if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
+ });
- var getIterationMethod = function (KIND) {
- if (KIND === DEFAULT && defaultIterator) return defaultIterator;
- if (!BUGGY_SAFARI_ITERATORS && KIND && KIND in IterablePrototype) return IterablePrototype[KIND];
+ var Prototype = Constructor.prototype;
- switch (KIND) {
- case KEYS: return function keys() { return new IteratorConstructor(this, KIND); };
- case VALUES: return function values() { return new IteratorConstructor(this, KIND); };
- case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); };
- }
+ var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
- return function () { return new IteratorConstructor(this); };
- };
+ var define = function (that, key, value) {
+ var state = getInternalState(that);
+ var data = getWeakData(anObject(key), true);
+ if (data === true) uncaughtFrozenStore(state).set(key, value);
+ else data[state.id] = value;
+ return that;
+ };
- var TO_STRING_TAG = NAME + ' Iterator';
- var INCORRECT_VALUES_NAME = false;
- var IterablePrototype = Iterable.prototype;
- var nativeIterator = IterablePrototype[ITERATOR]
- || IterablePrototype['@@iterator']
- || DEFAULT && IterablePrototype[DEFAULT];
- var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT);
- var anyNativeIterator = NAME === 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
- var CurrentIteratorPrototype, methods, KEY;
+ defineBuiltIns(Prototype, {
+ // `{ WeakMap, WeakSet }.prototype.delete(key)` methods
+ // https://tc39.es/ecma262/#sec-weakmap.prototype.delete
+ // https://tc39.es/ecma262/#sec-weakset.prototype.delete
+ 'delete': function (key) {
+ var state = getInternalState(this);
+ if (!isObject(key)) return false;
+ var data = getWeakData(key);
+ if (data === true) return uncaughtFrozenStore(state)['delete'](key);
+ return data && hasOwn(data, state.id) && delete data[state.id];
+ },
+ // `{ WeakMap, WeakSet }.prototype.has(key)` methods
+ // https://tc39.es/ecma262/#sec-weakmap.prototype.has
+ // https://tc39.es/ecma262/#sec-weakset.prototype.has
+ has: function has(key) {
+ var state = getInternalState(this);
+ if (!isObject(key)) return false;
+ var data = getWeakData(key);
+ if (data === true) return uncaughtFrozenStore(state).has(key);
+ return data && hasOwn(data, state.id);
+ }
+ });
- // fix native
- if (anyNativeIterator) {
- CurrentIteratorPrototype = getPrototypeOf(anyNativeIterator.call(new Iterable()));
- if (CurrentIteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {
- if (!IS_PURE && getPrototypeOf(CurrentIteratorPrototype) !== IteratorPrototype) {
- if (setPrototypeOf) {
- setPrototypeOf(CurrentIteratorPrototype, IteratorPrototype);
- } else if (!isCallable(CurrentIteratorPrototype[ITERATOR])) {
- defineBuiltIn(CurrentIteratorPrototype, ITERATOR, returnThis);
+ defineBuiltIns(Prototype, IS_MAP ? {
+ // `WeakMap.prototype.get(key)` method
+ // https://tc39.es/ecma262/#sec-weakmap.prototype.get
+ get: function get(key) {
+ var state = getInternalState(this);
+ if (isObject(key)) {
+ var data = getWeakData(key);
+ if (data === true) return uncaughtFrozenStore(state).get(key);
+ if (data) return data[state.id];
}
+ },
+ // `WeakMap.prototype.set(key, value)` method
+ // https://tc39.es/ecma262/#sec-weakmap.prototype.set
+ set: function set(key, value) {
+ return define(this, key, value);
}
- // Set @@toStringTag to native iterators
- setToStringTag(CurrentIteratorPrototype, TO_STRING_TAG, true, true);
- if (IS_PURE) Iterators[TO_STRING_TAG] = returnThis;
- }
- }
-
- // fix Array.prototype.{ values, @@iterator }.name in V8 / FF
- if (PROPER_FUNCTION_NAME && DEFAULT === VALUES && nativeIterator && nativeIterator.name !== VALUES) {
- if (!IS_PURE && CONFIGURABLE_FUNCTION_NAME) {
- createNonEnumerableProperty(IterablePrototype, 'name', VALUES);
- } else {
- INCORRECT_VALUES_NAME = true;
- defaultIterator = function values() { return call(nativeIterator, this); };
- }
- }
-
- // export additional methods
- if (DEFAULT) {
- methods = {
- values: getIterationMethod(VALUES),
- keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),
- entries: getIterationMethod(ENTRIES)
- };
- if (FORCED) for (KEY in methods) {
- if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
- defineBuiltIn(IterablePrototype, KEY, methods[KEY]);
+ } : {
+ // `WeakSet.prototype.add(value)` method
+ // https://tc39.es/ecma262/#sec-weakset.prototype.add
+ add: function add(value) {
+ return define(this, value, true);
}
- } else $({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
- }
+ });
- // define iterator
- if ((!IS_PURE || FORCED) && IterablePrototype[ITERATOR] !== defaultIterator) {
- defineBuiltIn(IterablePrototype, ITERATOR, defaultIterator, { name: DEFAULT });
+ return Constructor;
}
- Iterators[NAME] = defaultIterator;
-
- return methods;
};
/***/ }),
-/* 191 */
+/* 197 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
-var fails = __webpack_require__(33);
-var isCallable = __webpack_require__(46);
-var hasOwn = __webpack_require__(45);
-var DESCRIPTORS = __webpack_require__(38);
-var CONFIGURABLE_FUNCTION_NAME = __webpack_require__(113).CONFIGURABLE;
-var inspectSource = __webpack_require__(186);
-var InternalStateModule = __webpack_require__(53);
-
-var enforceInternalState = InternalStateModule.enforce;
-var getInternalState = InternalStateModule.get;
-var $String = String;
-// eslint-disable-next-line es/no-object-defineproperty -- safe
-var defineProperty = Object.defineProperty;
-var stringSlice = uncurryThis(''.slice);
-var replace = uncurryThis(''.replace);
-var join = uncurryThis([].join);
-
-var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function () {
- return defineProperty(function () { /* empty */ }, 'length', { value: 8 }).length !== 8;
-});
+var globalThis = __webpack_require__(3);
+var getBuiltInNodeModule = __webpack_require__(208);
+var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__(175);
-var TEMPLATE = String(String).split('String');
+var structuredClone = globalThis.structuredClone;
+var $ArrayBuffer = globalThis.ArrayBuffer;
+var $MessageChannel = globalThis.MessageChannel;
+var detach = false;
+var WorkerThreads, channel, buffer, $detach;
-var makeBuiltIn = module.exports = function (value, name, options) {
- if (stringSlice($String(name), 0, 7) === 'Symbol(') {
- name = '[' + replace($String(name), /^Symbol\(([^)]*)\).*$/, '$1') + ']';
- }
- if (options && options.getter) name = 'get ' + name;
- if (options && options.setter) name = 'set ' + name;
- if (!hasOwn(value, 'name') || (CONFIGURABLE_FUNCTION_NAME && value.name !== name)) {
- if (DESCRIPTORS) defineProperty(value, 'name', { value: name, configurable: true });
- else value.name = name;
- }
- if (CONFIGURABLE_LENGTH && options && hasOwn(options, 'arity') && value.length !== options.arity) {
- defineProperty(value, 'length', { value: options.arity });
+if (PROPER_STRUCTURED_CLONE_TRANSFER) {
+ detach = function (transferable) {
+ structuredClone(transferable, { transfer: [transferable] });
+ };
+} else if ($ArrayBuffer) try {
+ if (!$MessageChannel) {
+ WorkerThreads = getBuiltInNodeModule('worker_threads');
+ if (WorkerThreads) $MessageChannel = WorkerThreads.MessageChannel;
}
- try {
- if (options && hasOwn(options, 'constructor') && options.constructor) {
- if (DESCRIPTORS) defineProperty(value, 'prototype', { writable: false });
- // in V8 ~ Chrome 53, prototypes of some methods, like `Array.prototype.values`, are non-writable
- } else if (value.prototype) value.prototype = undefined;
- } catch (error) { /* empty */ }
- var state = enforceInternalState(value);
- if (!hasOwn(state, 'source')) {
- state.source = join(TEMPLATE, typeof name == 'string' ? name : '');
- } return value;
-};
-
-// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
-// eslint-disable-next-line no-extend-native -- required
-Function.prototype.toString = makeBuiltIn(function toString() {
- return isCallable(this) && getInternalState(this).source || inspectSource(this);
-}, 'toString');
+ if ($MessageChannel) {
+ channel = new $MessageChannel();
+ buffer = new $ArrayBuffer(2);
-/***/ }),
-/* 192 */
-/***/ (function(module, exports, __webpack_require__) {
+ $detach = function (transferable) {
+ channel.port1.postMessage(null, [transferable]);
+ };
-"use strict";
+ if (buffer.byteLength === 2) {
+ $detach(buffer);
+ if (buffer.byteLength === 0) detach = $detach;
+ }
+ }
+} catch (error) { /* empty */ }
-// `Math.sign` method implementation
-// https://tc39.es/ecma262/#sec-math.sign
-// eslint-disable-next-line es/no-math-sign -- safe
-module.exports = Math.sign || function sign(x) {
- var n = +x;
- // eslint-disable-next-line no-self-compare -- NaN check
- return n === 0 || n !== n ? n : n < 0 ? -1 : 1;
-};
+module.exports = detach;
/***/ }),
-/* 193 */
+/* 198 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isRegExp = __webpack_require__(152);
-
-var $TypeError = TypeError;
-
-module.exports = function (it) {
- if (isRegExp(it)) {
- throw new $TypeError("The method doesn't accept regular expressions");
- } return it;
+module.exports = {
+ IndexSizeError: { s: 'INDEX_SIZE_ERR', c: 1, m: 1 },
+ DOMStringSizeError: { s: 'DOMSTRING_SIZE_ERR', c: 2, m: 0 },
+ HierarchyRequestError: { s: 'HIERARCHY_REQUEST_ERR', c: 3, m: 1 },
+ WrongDocumentError: { s: 'WRONG_DOCUMENT_ERR', c: 4, m: 1 },
+ InvalidCharacterError: { s: 'INVALID_CHARACTER_ERR', c: 5, m: 1 },
+ NoDataAllowedError: { s: 'NO_DATA_ALLOWED_ERR', c: 6, m: 0 },
+ NoModificationAllowedError: { s: 'NO_MODIFICATION_ALLOWED_ERR', c: 7, m: 1 },
+ NotFoundError: { s: 'NOT_FOUND_ERR', c: 8, m: 1 },
+ NotSupportedError: { s: 'NOT_SUPPORTED_ERR', c: 9, m: 1 },
+ InUseAttributeError: { s: 'INUSE_ATTRIBUTE_ERR', c: 10, m: 1 },
+ InvalidStateError: { s: 'INVALID_STATE_ERR', c: 11, m: 1 },
+ SyntaxError: { s: 'SYNTAX_ERR', c: 12, m: 1 },
+ InvalidModificationError: { s: 'INVALID_MODIFICATION_ERR', c: 13, m: 1 },
+ NamespaceError: { s: 'NAMESPACE_ERR', c: 14, m: 1 },
+ InvalidAccessError: { s: 'INVALID_ACCESS_ERR', c: 15, m: 1 },
+ ValidationError: { s: 'VALIDATION_ERR', c: 16, m: 0 },
+ TypeMismatchError: { s: 'TYPE_MISMATCH_ERR', c: 17, m: 1 },
+ SecurityError: { s: 'SECURITY_ERR', c: 18, m: 1 },
+ NetworkError: { s: 'NETWORK_ERR', c: 19, m: 1 },
+ AbortError: { s: 'ABORT_ERR', c: 20, m: 1 },
+ URLMismatchError: { s: 'URL_MISMATCH_ERR', c: 21, m: 1 },
+ QuotaExceededError: { s: 'QUOTA_EXCEEDED_ERR', c: 22, m: 1 },
+ TimeoutError: { s: 'TIMEOUT_ERR', c: 23, m: 1 },
+ InvalidNodeTypeError: { s: 'INVALID_NODE_TYPE_ERR', c: 24, m: 1 },
+ DataCloneError: { s: 'DATA_CLONE_ERR', c: 25, m: 1 }
};
/***/ }),
-/* 194 */
+/* 199 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var DESCRIPTORS = __webpack_require__(38);
-var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__(279);
-var definePropertyModule = __webpack_require__(51);
-var anObject = __webpack_require__(37);
-var toIndexedObject = __webpack_require__(57);
-var objectKeys = __webpack_require__(134);
-
-// `Object.defineProperties` method
-// https://tc39.es/ecma262/#sec-object.defineproperties
-// eslint-disable-next-line es/no-object-defineproperties -- safe
-exports.f = DESCRIPTORS && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) {
- anObject(O);
- var props = toIndexedObject(Properties);
- var keys = objectKeys(Properties);
- var length = keys.length;
- var index = 0;
- var key;
- while (length > index) definePropertyModule.f(O, key = keys[index++], props[key]);
- return O;
+// iterable DOM collections
+// flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods
+module.exports = {
+ CSSRuleList: 0,
+ CSSStyleDeclaration: 0,
+ CSSValueList: 0,
+ ClientRectList: 0,
+ DOMRectList: 0,
+ DOMStringList: 0,
+ DOMTokenList: 1,
+ DataTransferItemList: 0,
+ FileList: 0,
+ HTMLAllCollection: 0,
+ HTMLCollection: 0,
+ HTMLFormElement: 0,
+ HTMLSelectElement: 0,
+ MediaList: 0,
+ MimeTypeArray: 0,
+ NamedNodeMap: 0,
+ NodeList: 1,
+ PaintRequestList: 0,
+ Plugin: 0,
+ PluginArray: 0,
+ SVGLengthList: 0,
+ SVGNumberList: 0,
+ SVGPathSegList: 0,
+ SVGPointList: 0,
+ SVGStringList: 0,
+ SVGTransformList: 0,
+ SourceBufferList: 0,
+ StyleSheetList: 0,
+ TextTrackCueList: 0,
+ TextTrackList: 0,
+ TouchList: 0
};
/***/ }),
-/* 195 */
+/* 200 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-/* eslint-disable es/no-object-getownpropertynames -- safe */
-var classof = __webpack_require__(64);
-var toIndexedObject = __webpack_require__(57);
-var $getOwnPropertyNames = __webpack_require__(106).f;
-var arraySlice = __webpack_require__(78);
-
-var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames
- ? Object.getOwnPropertyNames(window) : [];
-
-var getWindowNames = function (it) {
- try {
- return $getOwnPropertyNames(it);
- } catch (error) {
- return arraySlice(windowNames);
- }
-};
+// in old WebKit versions, `element.classList` is not an instance of global `DOMTokenList`
+var documentCreateElement = __webpack_require__(118);
-// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
-module.exports.f = function getOwnPropertyNames(it) {
- return windowNames && classof(it) === 'Window'
- ? getWindowNames(it)
- : $getOwnPropertyNames(toIndexedObject(it));
-};
+var classList = documentCreateElement('span').classList;
+var DOMTokenListPrototype = classList && classList.constructor && classList.constructor.prototype;
+
+module.exports = DOMTokenListPrototype === Object.prototype ? undefined : DOMTokenListPrototype;
/***/ }),
-/* 196 */
+/* 201 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var fails = __webpack_require__(33);
-var isObject = __webpack_require__(40);
-var classof = __webpack_require__(64);
-var ARRAY_BUFFER_NON_EXTENSIBLE = __webpack_require__(174);
+var userAgent = __webpack_require__(51);
-// eslint-disable-next-line es/no-object-isextensible -- safe
-var $isExtensible = Object.isExtensible;
-var FAILS_ON_PRIMITIVES = fails(function () { $isExtensible(1); });
+var firefox = userAgent.match(/firefox\/(\d+)/i);
-// `Object.isExtensible` method
-// https://tc39.es/ecma262/#sec-object.isextensible
-module.exports = (FAILS_ON_PRIMITIVES || ARRAY_BUFFER_NON_EXTENSIBLE) ? function isExtensible(it) {
- if (!isObject(it)) return false;
- if (ARRAY_BUFFER_NON_EXTENSIBLE && classof(it) === 'ArrayBuffer') return false;
- return $isExtensible ? $isExtensible(it) : true;
-} : $isExtensible;
+module.exports = !!firefox && +firefox[1];
/***/ }),
-/* 197 */
+/* 202 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var getBuiltIn = __webpack_require__(43);
-var uncurryThis = __webpack_require__(34);
-var getOwnPropertyNamesModule = __webpack_require__(106);
-var getOwnPropertySymbolsModule = __webpack_require__(155);
-var anObject = __webpack_require__(37);
+var UA = __webpack_require__(51);
-var concat = uncurryThis([].concat);
+module.exports = /MSIE|Trident/.test(UA);
-// all object keys, includes non-enumerable and symbols
-module.exports = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {
- var keys = getOwnPropertyNamesModule.f(anObject(it));
- var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
- return getOwnPropertySymbols ? concat(keys, getOwnPropertySymbols(it)) : keys;
-};
+
+/***/ }),
+/* 203 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+var userAgent = __webpack_require__(51);
+
+// eslint-disable-next-line redos/no-vulnerable -- safe
+module.exports = /(?:ipad|iphone|ipod).*applewebkit/i.test(userAgent);
/***/ }),
-/* 198 */
+/* 204 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-/* eslint-disable regexp/no-empty-capturing-group, regexp/no-empty-group, regexp/no-lazy-ends -- testing */
-/* eslint-disable regexp/no-useless-quantifier -- testing */
-var call = __webpack_require__(36);
-var uncurryThis = __webpack_require__(34);
-var toString = __webpack_require__(41);
-var regexpFlags = __webpack_require__(199);
-var stickyHelpers = __webpack_require__(160);
-var shared = __webpack_require__(123);
-var create = __webpack_require__(62);
-var getInternalState = __webpack_require__(53).get;
-var UNSUPPORTED_DOT_ALL = __webpack_require__(200);
-var UNSUPPORTED_NCG = __webpack_require__(267);
+var fails = __webpack_require__(1);
+var createPropertyDescriptor = __webpack_require__(41);
-var nativeReplace = shared('native-string-replace', String.prototype.replace);
-var nativeExec = RegExp.prototype.exec;
-var patchedExec = nativeExec;
-var charAt = uncurryThis(''.charAt);
-var indexOf = uncurryThis(''.indexOf);
-var replace = uncurryThis(''.replace);
-var stringSlice = uncurryThis(''.slice);
+module.exports = !fails(function () {
+ var error = new Error('a');
+ if (!('stack' in error)) return true;
+ // eslint-disable-next-line es/no-object-defineproperty -- safe
+ Object.defineProperty(error, 'stack', createPropertyDescriptor(1, 7));
+ return error.stack !== 7;
+});
-var UPDATES_LAST_INDEX_WRONG = (function () {
- var re1 = /a/;
- var re2 = /b*/g;
- call(nativeExec, re1, 'a');
- call(nativeExec, re2, 'a');
- return re1.lastIndex !== 0 || re2.lastIndex !== 0;
-})();
-var UNSUPPORTED_Y = stickyHelpers.BROKEN_CARET;
+/***/ }),
+/* 205 */
+/***/ (function(module, exports, __webpack_require__) {
-// nonparticipating capturing group, copied from es5-shim's String#split patch.
-var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;
+"use strict";
-var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y || UNSUPPORTED_DOT_ALL || UNSUPPORTED_NCG;
+var DESCRIPTORS = __webpack_require__(6);
+var fails = __webpack_require__(1);
+var anObject = __webpack_require__(5);
+var normalizeStringArgument = __webpack_require__(87);
-if (PATCH) {
- patchedExec = function exec(string) {
- var re = this;
- var state = getInternalState(re);
- var str = toString(string);
- var raw = state.raw;
- var result, reCopy, lastIndex, match, i, object, group;
+var nativeErrorToString = Error.prototype.toString;
- if (raw) {
- raw.lastIndex = re.lastIndex;
- result = call(patchedExec, raw, str);
- re.lastIndex = raw.lastIndex;
- return result;
- }
+var INCORRECT_TO_STRING = fails(function () {
+ if (DESCRIPTORS) {
+ // Chrome 32- incorrectly call accessor
+ // eslint-disable-next-line es/no-object-create, es/no-object-defineproperty -- safe
+ var object = Object.create(Object.defineProperty({}, 'name', { get: function () {
+ return this === object;
+ } }));
+ if (nativeErrorToString.call(object) !== 'true') return true;
+ }
+ // FF10- does not properly handle non-strings
+ return nativeErrorToString.call({ message: 1, name: 2 }) !== '2: 1'
+ // IE8 does not properly handle defaults
+ || nativeErrorToString.call({}) !== 'Error';
+});
- var groups = state.groups;
- var sticky = UNSUPPORTED_Y && re.sticky;
- var flags = call(regexpFlags, re);
- var source = re.source;
- var charsAdded = 0;
- var strCopy = str;
+module.exports = INCORRECT_TO_STRING ? function toString() {
+ var O = anObject(this);
+ var name = normalizeStringArgument(O.name, 'Error');
+ var message = normalizeStringArgument(O.message);
+ return !name ? message : !message ? name : name + ': ' + message;
+} : nativeErrorToString;
- if (sticky) {
- flags = replace(flags, 'y', '');
- if (indexOf(flags, 'g') === -1) {
- flags += 'g';
- }
- strCopy = stringSlice(str, re.lastIndex);
- // Support anchored sticky behavior.
- if (re.lastIndex > 0 && (!re.multiline || re.multiline && charAt(str, re.lastIndex - 1) !== '\n')) {
- source = '(?: ' + source + ')';
- strCopy = ' ' + strCopy;
- charsAdded++;
- }
- // ^(? + rx + ) is needed, in combination with some str slicing, to
- // simulate the 'y' flag.
- reCopy = new RegExp('^(?:' + source + ')', flags);
- }
+/***/ }),
+/* 206 */
+/***/ (function(module, exports, __webpack_require__) {
- if (NPCG_INCLUDED) {
- reCopy = new RegExp('^' + source + '$(?!\\s)', flags);
- }
- if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex;
+"use strict";
- match = call(nativeExec, sticky ? reCopy : re, strCopy);
+var isArray = __webpack_require__(62);
+var lengthOfArrayLike = __webpack_require__(18);
+var doesNotExceedSafeInteger = __webpack_require__(66);
+var bind = __webpack_require__(43);
- if (sticky) {
- if (match) {
- match.input = stringSlice(match.input, charsAdded);
- match[0] = stringSlice(match[0], charsAdded);
- match.index = re.lastIndex;
- re.lastIndex += match[0].length;
- } else re.lastIndex = 0;
- } else if (UPDATES_LAST_INDEX_WRONG && match) {
- re.lastIndex = re.global ? match.index + match[0].length : lastIndex;
- }
- if (NPCG_INCLUDED && match && match.length > 1) {
- // Fix browsers whose `exec` methods don't consistently return `undefined`
- // for NPCG, like IE8. NOTE: This doesn't work for /(.?)?/
- call(nativeReplace, match[0], reCopy, function () {
- for (i = 1; i < arguments.length - 2; i++) {
- if (arguments[i] === undefined) match[i] = undefined;
- }
- });
- }
+// `FlattenIntoArray` abstract operation
+// https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
+var flattenIntoArray = function (target, original, source, sourceLen, start, depth, mapper, thisArg) {
+ var targetIndex = start;
+ var sourceIndex = 0;
+ var mapFn = mapper ? bind(mapper, thisArg) : false;
+ var element, elementLen;
- if (match && groups) {
- match.groups = object = create(null);
- for (i = 0; i < groups.length; i++) {
- group = groups[i];
- object[group[0]] = match[group[1]];
+ while (sourceIndex < sourceLen) {
+ if (sourceIndex in source) {
+ element = mapFn ? mapFn(source[sourceIndex], sourceIndex, original) : source[sourceIndex];
+
+ if (depth > 0 && isArray(element)) {
+ elementLen = lengthOfArrayLike(element);
+ targetIndex = flattenIntoArray(target, original, element, elementLen, targetIndex, depth - 1) - 1;
+ } else {
+ doesNotExceedSafeInteger(targetIndex + 1);
+ target[targetIndex] = element;
}
- }
- return match;
- };
-}
+ targetIndex++;
+ }
+ sourceIndex++;
+ }
+ return targetIndex;
+};
-module.exports = patchedExec;
+module.exports = flattenIntoArray;
/***/ }),
-/* 199 */
+/* 207 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var anObject = __webpack_require__(37);
+var uncurryThis = __webpack_require__(2);
+var aCallable = __webpack_require__(10);
+var isObject = __webpack_require__(8);
+var hasOwn = __webpack_require__(13);
+var arraySlice = __webpack_require__(46);
+var NATIVE_BIND = __webpack_require__(99);
-// `RegExp.prototype.flags` getter implementation
-// https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
-module.exports = function () {
- var that = anObject(this);
- var result = '';
- if (that.hasIndices) result += 'd';
- if (that.global) result += 'g';
- if (that.ignoreCase) result += 'i';
- if (that.multiline) result += 'm';
- if (that.dotAll) result += 's';
- if (that.unicode) result += 'u';
- if (that.unicodeSets) result += 'v';
- if (that.sticky) result += 'y';
- return result;
+var $Function = Function;
+var concat = uncurryThis([].concat);
+var join = uncurryThis([].join);
+var factories = {};
+
+var construct = function (C, argsLength, args) {
+ if (!hasOwn(factories, argsLength)) {
+ var list = [];
+ var i = 0;
+ for (; i < argsLength; i++) list[i] = 'a[' + i + ']';
+ factories[argsLength] = $Function('C,a', 'return new C(' + join(list, ',') + ')');
+ } return factories[argsLength](C, args);
+};
+
+// `Function.prototype.bind` method implementation
+// https://tc39.es/ecma262/#sec-function.prototype.bind
+// eslint-disable-next-line es/no-function-prototype-bind -- detection
+module.exports = NATIVE_BIND ? $Function.bind : function bind(that /* , ...args */) {
+ var F = aCallable(this);
+ var Prototype = F.prototype;
+ var partArgs = arraySlice(arguments, 1);
+ var boundFunction = function bound(/* args... */) {
+ var args = concat(partArgs, arraySlice(arguments));
+ return this instanceof boundFunction ? construct(F, args.length, args) : F.apply(that, args);
+ };
+ if (isObject(Prototype)) boundFunction.prototype = Prototype;
+ return boundFunction;
};
/***/ }),
-/* 200 */
+/* 208 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var fails = __webpack_require__(33);
-var globalThis = __webpack_require__(35);
+var globalThis = __webpack_require__(3);
+var IS_NODE = __webpack_require__(80);
-// babel-minify and Closure Compiler transpiles RegExp('.', 's') -> /./s and it causes SyntaxError
-var $RegExp = globalThis.RegExp;
-
-module.exports = fails(function () {
- var re = $RegExp('.', 's');
- return !(re.dotAll && re.test('\n') && re.flags === 's');
-});
+module.exports = function (name) {
+ if (IS_NODE) {
+ try {
+ return globalThis.process.getBuiltinModule(name);
+ } catch (error) { /* empty */ }
+ try {
+ // eslint-disable-next-line no-new-func -- safe
+ return Function('return require("' + name + '")')();
+ } catch (error) { /* empty */ }
+ }
+};
/***/ }),
-/* 201 */
+/* 209 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var apply = __webpack_require__(74);
-var isCallable = __webpack_require__(46);
-var ENVIRONMENT = __webpack_require__(149);
-var USER_AGENT = __webpack_require__(83);
-var arraySlice = __webpack_require__(78);
-var validateArgumentsLength = __webpack_require__(80);
-
-var Function = globalThis.Function;
-// dirty IE9- and Bun 0.3.0- checks
-var WRAP = /MSIE .\./.test(USER_AGENT) || ENVIRONMENT === 'BUN' && (function () {
- var version = globalThis.Bun.version.split('.');
- return version.length < 3 || version[0] === '0' && (version[1] < 3 || version[1] === '3' && version[2] === '0');
-})();
+var globalThis = __webpack_require__(3);
-// IE9- / Bun 0.3.0- setTimeout / setInterval / setImmediate additional parameters fix
-// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
-// https://github.com/oven-sh/bun/issues/1633
-module.exports = function (scheduler, hasTimeArg) {
- var firstParamIndex = hasTimeArg ? 2 : 1;
- return WRAP ? function (handler, timeout /* , ...arguments */) {
- var boundArgs = validateArgumentsLength(arguments.length, 1) > firstParamIndex;
- var fn = isCallable(handler) ? handler : Function(handler);
- var params = boundArgs ? arraySlice(arguments, firstParamIndex) : [];
- var callback = boundArgs ? function () {
- apply(fn, this, params);
- } : fn;
- return hasTimeArg ? scheduler(callback, timeout) : scheduler(callback);
- } : scheduler;
+module.exports = function (CONSTRUCTOR, METHOD) {
+ var Constructor = globalThis[CONSTRUCTOR];
+ var Prototype = Constructor && Constructor.prototype;
+ return Prototype && Prototype[METHOD];
};
/***/ }),
-/* 202 */
+/* 210 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var SetHelpers = __webpack_require__(82);
-var iterate = __webpack_require__(121);
-
-var Set = SetHelpers.Set;
-var add = SetHelpers.add;
+var call = __webpack_require__(4);
+var anObject = __webpack_require__(5);
+var getIteratorDirect = __webpack_require__(33);
+var getIteratorMethod = __webpack_require__(68);
-module.exports = function (set) {
- var result = new Set();
- iterate(set, function (it) {
- add(result, it);
- });
- return result;
+module.exports = function (obj, stringHandling) {
+ if (!stringHandling || typeof obj !== 'string') anObject(obj);
+ var method = getIteratorMethod(obj);
+ return getIteratorDirect(anObject(method !== undefined ? call(method, obj) : obj));
};
/***/ }),
-/* 203 */
+/* 211 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var PROPER_FUNCTION_NAME = __webpack_require__(113).PROPER;
-var fails = __webpack_require__(33);
-var whitespaces = __webpack_require__(138);
+var uncurryThis = __webpack_require__(2);
+var toObject = __webpack_require__(15);
-var non = '\u200B\u0085\u180E';
+var floor = Math.floor;
+var charAt = uncurryThis(''.charAt);
+var replace = uncurryThis(''.replace);
+var stringSlice = uncurryThis(''.slice);
+// eslint-disable-next-line redos/no-vulnerable -- safe
+var SUBSTITUTION_SYMBOLS = /\$([$&'`]|\d{1,2}|<[^>]*>)/g;
+var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&'`]|\d{1,2})/g;
-// check that a method works with the correct list
-// of whitespaces and has a correct name
-module.exports = function (METHOD_NAME) {
- return fails(function () {
- return !!whitespaces[METHOD_NAME]()
- || non[METHOD_NAME]() !== non
- || (PROPER_FUNCTION_NAME && whitespaces[METHOD_NAME].name !== METHOD_NAME);
+// `GetSubstitution` abstract operation
+// https://tc39.es/ecma262/#sec-getsubstitution
+module.exports = function (matched, str, position, captures, namedCaptures, replacement) {
+ var tailPos = position + matched.length;
+ var m = captures.length;
+ var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
+ if (namedCaptures !== undefined) {
+ namedCaptures = toObject(namedCaptures);
+ symbols = SUBSTITUTION_SYMBOLS;
+ }
+ return replace(replacement, symbols, function (match, ch) {
+ var capture;
+ switch (charAt(ch, 0)) {
+ case '$': return '$';
+ case '&': return matched;
+ case '`': return stringSlice(str, 0, position);
+ case "'": return stringSlice(str, tailPos);
+ case '<':
+ capture = namedCaptures[stringSlice(ch, 1, -1)];
+ break;
+ default: // \d\d?
+ var n = +ch;
+ if (n === 0) return match;
+ if (n > m) {
+ var f = floor(n / 10);
+ if (f === 0) return match;
+ if (f <= m) return captures[f - 1] === undefined ? charAt(ch, 1) : captures[f - 1] + charAt(ch, 1);
+ return match;
+ }
+ capture = captures[n - 1];
+ }
+ return capture === undefined ? '' : capture;
});
};
/***/ }),
-/* 204 */
+/* 212 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var fails = __webpack_require__(33);
-var V8 = __webpack_require__(84);
-var ENVIRONMENT = __webpack_require__(149);
-
-var structuredClone = globalThis.structuredClone;
+var getBuiltIn = __webpack_require__(11);
-module.exports = !!structuredClone && !fails(function () {
- // prevent V8 ArrayBufferDetaching protector cell invalidation and performance degradation
- // https://github.com/zloirock/core-js/issues/679
- if ((ENVIRONMENT === 'DENO' && V8 > 92) || (ENVIRONMENT === 'NODE' && V8 > 94) || (ENVIRONMENT === 'BROWSER' && V8 > 97)) return false;
- var buffer = new ArrayBuffer(8);
- var clone = structuredClone(buffer, { transfer: [buffer] });
- return buffer.byteLength !== 0 || clone.byteLength !== 8;
-});
+module.exports = getBuiltIn('document', 'documentElement');
/***/ }),
-/* 205 */
+/* 213 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var toPrimitive = __webpack_require__(170);
+var DESCRIPTORS = __webpack_require__(6);
+var fails = __webpack_require__(1);
+var createElement = __webpack_require__(118);
-var $TypeError = TypeError;
-
-// `ToBigInt` abstract operation
-// https://tc39.es/ecma262/#sec-tobigint
-module.exports = function (argument) {
- var prim = toPrimitive(argument, 'number');
- if (typeof prim == 'number') throw new $TypeError("Can't convert number to bigint");
- // eslint-disable-next-line es/no-bigint -- safe
- return BigInt(prim);
-};
+// Thanks to IE8 for its funny defineProperty
+module.exports = !DESCRIPTORS && !fails(function () {
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
+ return Object.defineProperty(createElement('div'), 'a', {
+ get: function () { return 7; }
+ }).a !== 7;
+});
/***/ }),
-/* 206 */
+/* 214 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var toIntegerOrInfinity = __webpack_require__(54);
-
-var $RangeError = RangeError;
+var isObject = __webpack_require__(8);
+var createNonEnumerableProperty = __webpack_require__(27);
-module.exports = function (it) {
- var result = toIntegerOrInfinity(it);
- if (result < 0) throw new $RangeError("The argument can't be less than 0");
- return result;
+// `InstallErrorCause` abstract operation
+// https://tc39.es/proposal-error-cause/#sec-errorobjects-install-error-cause
+module.exports = function (O, options) {
+ if (isObject(options) && 'cause' in options) {
+ createNonEnumerableProperty(O, 'cause', options.cause);
+ }
};
/***/ }),
-/* 207 */
+/* 215 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var wellKnownSymbol = __webpack_require__(39);
-
-var TO_STRING_TAG = wellKnownSymbol('toStringTag');
-var test = {};
-
-test[TO_STRING_TAG] = 'z';
+var classof = __webpack_require__(47);
-module.exports = String(test) === '[object z]';
+module.exports = function (it) {
+ var klass = classof(it);
+ return klass === 'BigInt64Array' || klass === 'BigUint64Array';
+};
/***/ }),
-/* 208 */
+/* 216 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-/* eslint-disable no-new, sonarjs/inconsistent-function-call -- required for testing */
-var globalThis = __webpack_require__(35);
-var fails = __webpack_require__(33);
-var checkCorrectnessOfIteration = __webpack_require__(145);
-var NATIVE_ARRAY_BUFFER_VIEWS = __webpack_require__(44).NATIVE_ARRAY_BUFFER_VIEWS;
-
-var ArrayBuffer = globalThis.ArrayBuffer;
-var Int8Array = globalThis.Int8Array;
+var hasOwn = __webpack_require__(13);
-module.exports = !NATIVE_ARRAY_BUFFER_VIEWS || !fails(function () {
- Int8Array(1);
-}) || !fails(function () {
- new Int8Array(-1);
-}) || !checkCorrectnessOfIteration(function (iterable) {
- new Int8Array();
- new Int8Array(null);
- new Int8Array(1.5);
- new Int8Array(iterable);
-}, true) || fails(function () {
- // Safari (11+) bug - a reason why even Safari 13 should load a typed array polyfill
- return new Int8Array(new ArrayBuffer(2), 1, undefined).length !== 1;
-});
+module.exports = function (descriptor) {
+ return descriptor !== undefined && (hasOwn(descriptor, 'value') || hasOwn(descriptor, 'writable'));
+};
/***/ }),
-/* 209 */
+/* 217 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var $ = __webpack_require__(32);
-var exec = __webpack_require__(198);
+var isObject = __webpack_require__(8);
-// `RegExp.prototype.exec` method
-// https://tc39.es/ecma262/#sec-regexp.prototype.exec
-$({ target: 'RegExp', proto: true, forced: /./.exec !== exec }, {
- exec: exec
-});
+module.exports = function (argument) {
+ return isObject(argument) || argument === null;
+};
/***/ }),
-/* 210 */
+/* 218 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isPossiblePrototype = __webpack_require__(246);
+var uncurryThis = __webpack_require__(2);
-var $String = String;
-var $TypeError = TypeError;
+// eslint-disable-next-line es/no-map -- safe
+var MapPrototype = Map.prototype;
-module.exports = function (argument) {
- if (isPossiblePrototype(argument)) return argument;
- throw new $TypeError("Can't set " + $String(argument) + ' as a prototype');
+module.exports = {
+ // eslint-disable-next-line es/no-map -- safe
+ Map: Map,
+ set: uncurryThis(MapPrototype.set),
+ get: uncurryThis(MapPrototype.get),
+ has: uncurryThis(MapPrototype.has),
+ remove: uncurryThis(MapPrototype['delete']),
+ proto: MapPrototype
};
/***/ }),
-/* 211 */
+/* 219 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var getBuiltIn = __webpack_require__(43);
-var call = __webpack_require__(36);
-var uncurryThis = __webpack_require__(34);
-var bind = __webpack_require__(75);
-var anObject = __webpack_require__(37);
-var aCallable = __webpack_require__(42);
-var isNullOrUndefined = __webpack_require__(89);
-var getMethod = __webpack_require__(60);
-var wellKnownSymbol = __webpack_require__(39);
+var sign = __webpack_require__(163);
+var roundTiesToEven = __webpack_require__(224);
-var ASYNC_DISPOSE = wellKnownSymbol('asyncDispose');
-var DISPOSE = wellKnownSymbol('dispose');
+var abs = Math.abs;
-var push = uncurryThis([].push);
+var EPSILON = 2.220446049250313e-16; // Number.EPSILON
-// `GetDisposeMethod` abstract operation
-// https://tc39.es/proposal-explicit-resource-management/#sec-getdisposemethod
-var getDisposeMethod = function (V, hint) {
- if (hint === 'async-dispose') {
- var method = getMethod(V, ASYNC_DISPOSE);
- if (method !== undefined) return method;
- method = getMethod(V, DISPOSE);
- if (method === undefined) return method;
- return function () {
- var O = this;
- var Promise = getBuiltIn('Promise');
- return new Promise(function (resolve) {
- call(method, O);
- resolve(undefined);
- });
- };
- } return getMethod(V, DISPOSE);
+module.exports = function (x, FLOAT_EPSILON, FLOAT_MAX_VALUE, FLOAT_MIN_VALUE) {
+ var n = +x;
+ var absolute = abs(n);
+ var s = sign(n);
+ if (absolute < FLOAT_MIN_VALUE) return s * roundTiesToEven(absolute / FLOAT_MIN_VALUE / FLOAT_EPSILON) * FLOAT_MIN_VALUE * FLOAT_EPSILON;
+ var a = (1 + FLOAT_EPSILON / EPSILON) * absolute;
+ var result = a - (a - absolute);
+ // eslint-disable-next-line no-self-compare -- NaN check
+ if (result > FLOAT_MAX_VALUE || result !== result) return s * Infinity;
+ return s * result;
};
-// `CreateDisposableResource` abstract operation
-// https://tc39.es/proposal-explicit-resource-management/#sec-createdisposableresource
-var createDisposableResource = function (V, hint, method) {
- if (arguments.length < 3 && !isNullOrUndefined(V)) {
- method = aCallable(getDisposeMethod(anObject(V), hint));
- }
- return method === undefined ? function () {
- return undefined;
- } : bind(method, V);
-};
+/***/ }),
+/* 220 */
+/***/ (function(module, exports, __webpack_require__) {
-// `AddDisposableResource` abstract operation
-// https://tc39.es/proposal-explicit-resource-management/#sec-adddisposableresource
-module.exports = function (disposable, V, hint, method) {
- var resource;
- if (arguments.length < 4) {
- // When `V`` is either `null` or `undefined` and hint is `async-dispose`,
- // we record that the resource was evaluated to ensure we will still perform an `Await` when resources are later disposed.
- if (isNullOrUndefined(V) && hint === 'sync-dispose') return;
- resource = createDisposableResource(V, hint);
- } else {
- resource = createDisposableResource(undefined, hint, method);
- }
+"use strict";
+
+var floatRound = __webpack_require__(219);
+
+var FLOAT32_EPSILON = 1.1920928955078125e-7; // 2 ** -23;
+var FLOAT32_MAX_VALUE = 3.4028234663852886e+38; // 2 ** 128 - 2 ** 104
+var FLOAT32_MIN_VALUE = 1.1754943508222875e-38; // 2 ** -126;
- push(disposable.stack, resource);
+// `Math.fround` method implementation
+// https://tc39.es/ecma262/#sec-math.fround
+// eslint-disable-next-line es/no-math-fround -- safe
+module.exports = Math.fround || function fround(x) {
+ return floatRound(x, FLOAT32_EPSILON, FLOAT32_MAX_VALUE, FLOAT32_MIN_VALUE);
};
/***/ }),
-/* 212 */
+/* 221 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var uncurryThisAccessor = __webpack_require__(151);
-var classof = __webpack_require__(64);
-
-var ArrayBuffer = globalThis.ArrayBuffer;
-var TypeError = globalThis.TypeError;
+var log = Math.log;
+var LOG10E = Math.LOG10E;
-// Includes
-// - Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
-// - If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
-module.exports = ArrayBuffer && uncurryThisAccessor(ArrayBuffer.prototype, 'byteLength', 'get') || function (O) {
- if (classof(O) !== 'ArrayBuffer') throw new TypeError('ArrayBuffer expected');
- return O.byteLength;
+// eslint-disable-next-line es/no-math-log10 -- safe
+module.exports = Math.log10 || function log10(x) {
+ return log(x) * LOG10E;
};
/***/ }),
-/* 213 */
+/* 222 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var NATIVE_ARRAY_BUFFER = __webpack_require__(140);
-var arrayBufferByteLength = __webpack_require__(212);
-
-var DataView = globalThis.DataView;
+var log = Math.log;
-module.exports = function (O) {
- if (!NATIVE_ARRAY_BUFFER || arrayBufferByteLength(O) !== 0) return false;
- try {
- // eslint-disable-next-line no-new -- thrower
- new DataView(O);
- return false;
- } catch (error) {
- return true;
- }
+// `Math.log1p` method implementation
+// https://tc39.es/ecma262/#sec-math.log1p
+// eslint-disable-next-line es/no-math-log1p -- safe
+module.exports = Math.log1p || function log1p(x) {
+ var n = +x;
+ return n > -1e-8 && n < 1e-8 ? n - n * n / 2 : log(1 + n);
};
/***/ }),
-/* 214 */
+/* 223 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var uncurryThis = __webpack_require__(34);
-var uncurryThisAccessor = __webpack_require__(151);
-var toIndex = __webpack_require__(169);
-var notDetached = __webpack_require__(289);
-var arrayBufferByteLength = __webpack_require__(212);
-var detachTransferable = __webpack_require__(226);
-var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__(204);
-
-var structuredClone = globalThis.structuredClone;
-var ArrayBuffer = globalThis.ArrayBuffer;
-var DataView = globalThis.DataView;
-var min = Math.min;
-var ArrayBufferPrototype = ArrayBuffer.prototype;
-var DataViewPrototype = DataView.prototype;
-var slice = uncurryThis(ArrayBufferPrototype.slice);
-var isResizable = uncurryThisAccessor(ArrayBufferPrototype, 'resizable', 'get');
-var maxByteLength = uncurryThisAccessor(ArrayBufferPrototype, 'maxByteLength', 'get');
-var getInt8 = uncurryThis(DataViewPrototype.getInt8);
-var setInt8 = uncurryThis(DataViewPrototype.setInt8);
+var log = Math.log;
+var LN2 = Math.LN2;
-module.exports = (PROPER_STRUCTURED_CLONE_TRANSFER || detachTransferable) && function (arrayBuffer, newLength, preserveResizability) {
- var byteLength = arrayBufferByteLength(arrayBuffer);
- var newByteLength = newLength === undefined ? byteLength : toIndex(newLength);
- var fixedLength = !isResizable || !isResizable(arrayBuffer);
- var newBuffer;
- notDetached(arrayBuffer);
- if (PROPER_STRUCTURED_CLONE_TRANSFER) {
- arrayBuffer = structuredClone(arrayBuffer, { transfer: [arrayBuffer] });
- if (byteLength === newByteLength && (preserveResizability || fixedLength)) return arrayBuffer;
- }
- if (byteLength >= newByteLength && (!preserveResizability || fixedLength)) {
- newBuffer = slice(arrayBuffer, 0, newByteLength);
- } else {
- var options = preserveResizability && !fixedLength && maxByteLength ? { maxByteLength: maxByteLength(arrayBuffer) } : undefined;
- newBuffer = new ArrayBuffer(newByteLength, options);
- var a = new DataView(arrayBuffer);
- var b = new DataView(newBuffer);
- var copyLength = min(newByteLength, byteLength);
- for (var i = 0; i < copyLength; i++) setInt8(b, i, getInt8(a, i));
- }
- if (!PROPER_STRUCTURED_CLONE_TRANSFER) detachTransferable(arrayBuffer);
- return newBuffer;
+// `Math.log2` method
+// https://tc39.es/ecma262/#sec-math.log2
+// eslint-disable-next-line es/no-math-log2 -- safe
+module.exports = Math.log2 || function log2(x) {
+ return log(x) / LN2;
};
/***/ }),
-/* 215 */
+/* 224 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var toObject = __webpack_require__(47);
-var toAbsoluteIndex = __webpack_require__(91);
-var lengthOfArrayLike = __webpack_require__(50);
-var deletePropertyOrThrow = __webpack_require__(147);
-
-var min = Math.min;
+var EPSILON = 2.220446049250313e-16; // Number.EPSILON
+var INVERSE_EPSILON = 1 / EPSILON;
-// `Array.prototype.copyWithin` method implementation
-// https://tc39.es/ecma262/#sec-array.prototype.copywithin
-// eslint-disable-next-line es/no-array-prototype-copywithin -- safe
-module.exports = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) {
- var O = toObject(this);
- var len = lengthOfArrayLike(O);
- var to = toAbsoluteIndex(target, len);
- var from = toAbsoluteIndex(start, len);
- var end = arguments.length > 2 ? arguments[2] : undefined;
- var count = min((end === undefined ? len : toAbsoluteIndex(end, len)) - from, len - to);
- var inc = 1;
- if (from < to && to < from + count) {
- inc = -1;
- from += count - 1;
- to += count - 1;
- }
- while (count-- > 0) {
- if (from in O) O[to] = O[from];
- else deletePropertyOrThrow(O, to);
- to += inc;
- from += inc;
- } return O;
+module.exports = function (n) {
+ return n + INVERSE_EPSILON - INVERSE_EPSILON;
};
/***/ }),
-/* 216 */
+/* 225 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var $forEach = __webpack_require__(58).forEach;
-var arrayMethodIsStrict = __webpack_require__(86);
-
-var STRICT_METHOD = arrayMethodIsStrict('forEach');
+var ceil = Math.ceil;
+var floor = Math.floor;
-// `Array.prototype.forEach` method implementation
-// https://tc39.es/ecma262/#sec-array.prototype.foreach
-module.exports = !STRICT_METHOD ? function forEach(callbackfn /* , thisArg */) {
- return $forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
-// eslint-disable-next-line es/no-array-prototype-foreach -- safe
-} : [].forEach;
+// `Math.trunc` method
+// https://tc39.es/ecma262/#sec-math.trunc
+// eslint-disable-next-line es/no-math-trunc -- safe
+module.exports = Math.trunc || function trunc(x) {
+ var n = +x;
+ return (n > 0 ? floor : ceil)(n);
+};
/***/ }),
-/* 217 */
+/* 226 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var bind = __webpack_require__(75);
-var call = __webpack_require__(36);
-var toObject = __webpack_require__(47);
-var callWithSafeIterationClosing = __webpack_require__(178);
-var isArrayIteratorMethod = __webpack_require__(187);
-var isConstructor = __webpack_require__(103);
-var lengthOfArrayLike = __webpack_require__(50);
-var createProperty = __webpack_require__(87);
-var getIterator = __webpack_require__(114);
-var getIteratorMethod = __webpack_require__(99);
+var globalThis = __webpack_require__(3);
+var safeGetBuiltIn = __webpack_require__(239);
+var bind = __webpack_require__(43);
+var macrotask = __webpack_require__(137).set;
+var Queue = __webpack_require__(236);
+var IS_IOS = __webpack_require__(203);
+var IS_IOS_PEBBLE = __webpack_require__(291);
+var IS_WEBOS_WEBKIT = __webpack_require__(292);
+var IS_NODE = __webpack_require__(80);
-var $Array = Array;
+var MutationObserver = globalThis.MutationObserver || globalThis.WebKitMutationObserver;
+var document = globalThis.document;
+var process = globalThis.process;
+var Promise = globalThis.Promise;
+var microtask = safeGetBuiltIn('queueMicrotask');
+var notify, toggle, node, promise, then;
-// `Array.from` method implementation
-// https://tc39.es/ecma262/#sec-array.from
-module.exports = function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
- var O = toObject(arrayLike);
- var IS_CONSTRUCTOR = isConstructor(this);
- var argumentsLength = arguments.length;
- var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
- var mapping = mapfn !== undefined;
- if (mapping) mapfn = bind(mapfn, argumentsLength > 2 ? arguments[2] : undefined);
- var iteratorMethod = getIteratorMethod(O);
- var index = 0;
- var length, result, step, iterator, next, value;
- // if the target is not iterable or it's an array with the default iterator - use a simple case
- if (iteratorMethod && !(this === $Array && isArrayIteratorMethod(iteratorMethod))) {
- result = IS_CONSTRUCTOR ? new this() : [];
- iterator = getIterator(O, iteratorMethod);
- next = iterator.next;
- for (;!(step = call(next, iterator)).done; index++) {
- value = mapping ? callWithSafeIterationClosing(iterator, mapfn, [step.value, index], true) : step.value;
- createProperty(result, index, value);
+// modern engines have queueMicrotask method
+if (!microtask) {
+ var queue = new Queue();
+
+ var flush = function () {
+ var parent, fn;
+ if (IS_NODE && (parent = process.domain)) parent.exit();
+ while (fn = queue.get()) try {
+ fn();
+ } catch (error) {
+ if (queue.head) notify();
+ throw error;
}
+ if (parent) parent.enter();
+ };
+
+ // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339
+ // also except WebOS Webkit https://github.com/zloirock/core-js/issues/898
+ if (!IS_IOS && !IS_NODE && !IS_WEBOS_WEBKIT && MutationObserver && document) {
+ toggle = true;
+ node = document.createTextNode('');
+ new MutationObserver(flush).observe(node, { characterData: true });
+ notify = function () {
+ node.data = toggle = !toggle;
+ };
+ // environments with maybe non-completely correct, but existent Promise
+ } else if (!IS_IOS_PEBBLE && Promise && Promise.resolve) {
+ // Promise.resolve without an argument throws an error in LG WebOS 2
+ promise = Promise.resolve(undefined);
+ // workaround of WebKit ~ iOS Safari 10.1 bug
+ promise.constructor = Promise;
+ then = bind(promise.then, promise);
+ notify = function () {
+ then(flush);
+ };
+ // Node.js without promises
+ } else if (IS_NODE) {
+ notify = function () {
+ process.nextTick(flush);
+ };
+ // for other environments - macrotask based on:
+ // - setImmediate
+ // - MessageChannel
+ // - window.postMessage
+ // - onreadystatechange
+ // - setTimeout
} else {
- length = lengthOfArrayLike(O);
- result = IS_CONSTRUCTOR ? new this(length) : $Array(length);
- for (;length > index; index++) {
- value = mapping ? mapfn(O[index], index) : O[index];
- createProperty(result, index, value);
- }
+ // `webpack` dev server bug on IE global methods - use bind(fn, global)
+ macrotask = bind(macrotask, globalThis);
+ notify = function () {
+ macrotask(flush);
+ };
}
- result.length = index;
- return result;
-};
+
+ microtask = function (fn) {
+ if (!queue.head) notify();
+ queue.add(fn);
+ };
+}
+
+module.exports = microtask;
/***/ }),
-/* 218 */
+/* 227 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-/* eslint-disable es/no-array-prototype-lastindexof -- safe */
-var apply = __webpack_require__(74);
-var toIndexedObject = __webpack_require__(57);
-var toIntegerOrInfinity = __webpack_require__(54);
-var lengthOfArrayLike = __webpack_require__(50);
-var arrayMethodIsStrict = __webpack_require__(86);
-
-var min = Math.min;
-var $lastIndexOf = [].lastIndexOf;
-var NEGATIVE_ZERO = !!$lastIndexOf && 1 / [1].lastIndexOf(1, -0) < 0;
-var STRICT_METHOD = arrayMethodIsStrict('lastIndexOf');
-var FORCED = NEGATIVE_ZERO || !STRICT_METHOD;
+var $RangeError = RangeError;
-// `Array.prototype.lastIndexOf` method implementation
-// https://tc39.es/ecma262/#sec-array.prototype.lastindexof
-module.exports = FORCED ? function lastIndexOf(searchElement /* , fromIndex = @[*-1] */) {
- // convert -0 to +0
- if (NEGATIVE_ZERO) return apply($lastIndexOf, this, arguments) || 0;
- var O = toIndexedObject(this);
- var length = lengthOfArrayLike(O);
- if (length === 0) return -1;
- var index = length - 1;
- if (arguments.length > 1) index = min(index, toIntegerOrInfinity(arguments[1]));
- if (index < 0) index = length + index;
- for (;index >= 0; index--) if (index in O && O[index] === searchElement) return index || 0;
- return -1;
-} : $lastIndexOf;
+module.exports = function (it) {
+ // eslint-disable-next-line no-self-compare -- NaN check
+ if (it === it) return it;
+ throw new $RangeError('NaN is not allowed');
+};
/***/ }),
-/* 219 */
+/* 228 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var lengthOfArrayLike = __webpack_require__(50);
+var globalThis = __webpack_require__(3);
+var fails = __webpack_require__(1);
+var uncurryThis = __webpack_require__(2);
+var toString = __webpack_require__(9);
+var trim = __webpack_require__(93).trim;
+var whitespaces = __webpack_require__(107);
-// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toReversed
-// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toReversed
-module.exports = function (O, C) {
- var len = lengthOfArrayLike(O);
- var A = new C(len);
- var k = 0;
- for (; k < len; k++) A[k] = O[len - k - 1];
- return A;
-};
+var charAt = uncurryThis(''.charAt);
+var $parseFloat = globalThis.parseFloat;
+var Symbol = globalThis.Symbol;
+var ITERATOR = Symbol && Symbol.iterator;
+var FORCED = 1 / $parseFloat(whitespaces + '-0') !== -Infinity
+ // MS Edge 18- broken with boxed symbols
+ || (ITERATOR && !fails(function () { $parseFloat(Object(ITERATOR)); }));
+
+// `parseFloat` method
+// https://tc39.es/ecma262/#sec-parsefloat-string
+module.exports = FORCED ? function parseFloat(string) {
+ var trimmedString = trim(toString(string));
+ var result = $parseFloat(trimmedString);
+ return result === 0 && charAt(trimmedString, 0) === '-' ? -0 : result;
+} : $parseFloat;
/***/ }),
-/* 220 */
+/* 229 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var lengthOfArrayLike = __webpack_require__(50);
-var toIntegerOrInfinity = __webpack_require__(54);
+var globalThis = __webpack_require__(3);
+var fails = __webpack_require__(1);
+var uncurryThis = __webpack_require__(2);
+var toString = __webpack_require__(9);
+var trim = __webpack_require__(93).trim;
+var whitespaces = __webpack_require__(107);
-var $RangeError = RangeError;
+var $parseInt = globalThis.parseInt;
+var Symbol = globalThis.Symbol;
+var ITERATOR = Symbol && Symbol.iterator;
+var hex = /^[+-]?0x/i;
+var exec = uncurryThis(hex.exec);
+var FORCED = $parseInt(whitespaces + '08') !== 8 || $parseInt(whitespaces + '0x16') !== 22
+ // MS Edge 18- broken with boxed symbols
+ || (ITERATOR && !fails(function () { $parseInt(Object(ITERATOR)); }));
-// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.with
-// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.with
-module.exports = function (O, C, index, value) {
- var len = lengthOfArrayLike(O);
- var relativeIndex = toIntegerOrInfinity(index);
- var actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex;
- if (actualIndex >= len || actualIndex < 0) throw new $RangeError('Incorrect index');
- var A = new C(len);
- var k = 0;
- for (; k < len; k++) A[k] = k === actualIndex ? value : O[k];
- return A;
-};
+// `parseInt` method
+// https://tc39.es/ecma262/#sec-parseint-string-radix
+module.exports = FORCED ? function parseInt(string, radix) {
+ var S = trim(toString(string));
+ return $parseInt(S, (radix >>> 0) || (exec(hex, S) ? 16 : 10));
+} : $parseInt;
/***/ }),
-/* 221 */
+/* 230 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var call = __webpack_require__(36);
-var anObject = __webpack_require__(37);
-var create = __webpack_require__(62);
-var getMethod = __webpack_require__(60);
-var defineBuiltIns = __webpack_require__(88);
-var InternalStateModule = __webpack_require__(53);
-var iteratorClose = __webpack_require__(61);
-var getBuiltIn = __webpack_require__(43);
-var AsyncIteratorPrototype = __webpack_require__(222);
-var createIterResultObject = __webpack_require__(96);
-
-var Promise = getBuiltIn('Promise');
+var DESCRIPTORS = __webpack_require__(6);
+var uncurryThis = __webpack_require__(2);
+var call = __webpack_require__(4);
+var fails = __webpack_require__(1);
+var objectKeys = __webpack_require__(103);
+var getOwnPropertySymbolsModule = __webpack_require__(125);
+var propertyIsEnumerableModule = __webpack_require__(126);
+var toObject = __webpack_require__(15);
+var IndexedObject = __webpack_require__(84);
-var ASYNC_FROM_SYNC_ITERATOR = 'AsyncFromSyncIterator';
-var setInternalState = InternalStateModule.set;
-var getInternalState = InternalStateModule.getterFor(ASYNC_FROM_SYNC_ITERATOR);
+// eslint-disable-next-line es/no-object-assign -- safe
+var $assign = Object.assign;
+// eslint-disable-next-line es/no-object-defineproperty -- required for testing
+var defineProperty = Object.defineProperty;
+var concat = uncurryThis([].concat);
-var asyncFromSyncIteratorContinuation = function (result, resolve, reject, syncIterator, closeOnRejection) {
- var done = result.done;
- Promise.resolve(result.value).then(function (value) {
- resolve(createIterResultObject(value, done));
- }, function (error) {
- if (!done && closeOnRejection) {
- try {
- iteratorClose(syncIterator, 'throw', error);
- } catch (error2) {
- error = error2;
- }
+// `Object.assign` method
+// https://tc39.es/ecma262/#sec-object.assign
+module.exports = !$assign || fails(function () {
+ // should have correct order of operations (Edge bug)
+ if (DESCRIPTORS && $assign({ b: 1 }, $assign(defineProperty({}, 'a', {
+ enumerable: true,
+ get: function () {
+ defineProperty(this, 'b', {
+ value: 3,
+ enumerable: false
+ });
+ }
+ }), { b: 2 })).b !== 1) return true;
+ // should work with symbols and should have deterministic property order (V8 bug)
+ var A = {};
+ var B = {};
+ // eslint-disable-next-line es/no-symbol -- safe
+ var symbol = Symbol('assign detection');
+ var alphabet = 'abcdefghijklmnopqrst';
+ A[symbol] = 7;
+ // eslint-disable-next-line es/no-array-prototype-foreach -- safe
+ alphabet.split('').forEach(function (chr) { B[chr] = chr; });
+ return $assign({}, A)[symbol] !== 7 || objectKeys($assign({}, B)).join('') !== alphabet;
+}) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length`
+ var T = toObject(target);
+ var argumentsLength = arguments.length;
+ var index = 1;
+ var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
+ var propertyIsEnumerable = propertyIsEnumerableModule.f;
+ while (argumentsLength > index) {
+ var S = IndexedObject(arguments[index++]);
+ var keys = getOwnPropertySymbols ? concat(objectKeys(S), getOwnPropertySymbols(S)) : objectKeys(S);
+ var length = keys.length;
+ var j = 0;
+ var key;
+ while (length > j) {
+ key = keys[j++];
+ if (!DESCRIPTORS || call(propertyIsEnumerable, S, key)) T[key] = S[key];
}
+ } return T;
+} : $assign;
- reject(error);
- });
-};
-var AsyncFromSyncIterator = function AsyncIterator(iteratorRecord) {
- iteratorRecord.type = ASYNC_FROM_SYNC_ITERATOR;
- setInternalState(this, iteratorRecord);
-};
+/***/ }),
+/* 231 */
+/***/ (function(module, exports, __webpack_require__) {
-AsyncFromSyncIterator.prototype = defineBuiltIns(create(AsyncIteratorPrototype), {
- next: function next() {
- var state = getInternalState(this);
- return new Promise(function (resolve, reject) {
- var result = anObject(call(state.next, state.iterator));
- asyncFromSyncIteratorContinuation(result, resolve, reject, state.iterator, true);
- });
- },
- 'return': function () {
- var iterator = getInternalState(this).iterator;
- return new Promise(function (resolve, reject) {
- var $return = getMethod(iterator, 'return');
- if ($return === undefined) return resolve(createIterResultObject(undefined, true));
- var result = anObject(call($return, iterator));
- asyncFromSyncIteratorContinuation(result, resolve, reject, iterator);
- });
- }
-});
+"use strict";
-module.exports = AsyncFromSyncIterator;
+var uncurryThis = __webpack_require__(2);
+var hasOwn = __webpack_require__(13);
+var toIndexedObject = __webpack_require__(25);
+var indexOf = __webpack_require__(96).indexOf;
+var hiddenKeys = __webpack_require__(100);
+
+var push = uncurryThis([].push);
+
+module.exports = function (object, names) {
+ var O = toIndexedObject(object);
+ var i = 0;
+ var result = [];
+ var key;
+ for (key in O) !hasOwn(hiddenKeys, key) && hasOwn(O, key) && push(result, key);
+ // Don't enum bug & hidden keys
+ while (names.length > i) if (hasOwn(O, key = names[i++])) {
+ ~indexOf(result, key) || push(result, key);
+ }
+ return result;
+};
/***/ }),
-/* 222 */
+/* 232 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var shared = __webpack_require__(162);
-var isCallable = __webpack_require__(46);
-var create = __webpack_require__(62);
-var getPrototypeOf = __webpack_require__(67);
-var defineBuiltIn = __webpack_require__(49);
-var wellKnownSymbol = __webpack_require__(39);
-var IS_PURE = __webpack_require__(48);
-
-var USE_FUNCTION_CONSTRUCTOR = 'USE_FUNCTION_CONSTRUCTOR';
-var ASYNC_ITERATOR = wellKnownSymbol('asyncIterator');
-var AsyncIterator = globalThis.AsyncIterator;
-var PassedAsyncIteratorPrototype = shared.AsyncIteratorPrototype;
-var AsyncIteratorPrototype, prototype;
+var DESCRIPTORS = __webpack_require__(6);
+var fails = __webpack_require__(1);
+var uncurryThis = __webpack_require__(2);
+var objectGetPrototypeOf = __webpack_require__(35);
+var objectKeys = __webpack_require__(103);
+var toIndexedObject = __webpack_require__(25);
+var $propertyIsEnumerable = __webpack_require__(126).f;
-if (PassedAsyncIteratorPrototype) {
- AsyncIteratorPrototype = PassedAsyncIteratorPrototype;
-} else if (isCallable(AsyncIterator)) {
- AsyncIteratorPrototype = AsyncIterator.prototype;
-} else if (shared[USE_FUNCTION_CONSTRUCTOR] || globalThis[USE_FUNCTION_CONSTRUCTOR]) {
- try {
- // eslint-disable-next-line no-new-func -- we have no alternatives without usage of modern syntax
- prototype = getPrototypeOf(getPrototypeOf(getPrototypeOf(Function('return async function*(){}()')())));
- if (getPrototypeOf(prototype) === Object.prototype) AsyncIteratorPrototype = prototype;
- } catch (error) { /* empty */ }
-}
+var propertyIsEnumerable = uncurryThis($propertyIsEnumerable);
+var push = uncurryThis([].push);
-if (!AsyncIteratorPrototype) AsyncIteratorPrototype = {};
-else if (IS_PURE) AsyncIteratorPrototype = create(AsyncIteratorPrototype);
+// in some IE versions, `propertyIsEnumerable` returns incorrect result on integer keys
+// of `null` prototype objects
+var IE_BUG = DESCRIPTORS && fails(function () {
+ // eslint-disable-next-line es/no-object-create -- safe
+ var O = Object.create(null);
+ O[2] = 2;
+ return !propertyIsEnumerable(O, 2);
+});
-if (!isCallable(AsyncIteratorPrototype[ASYNC_ITERATOR])) {
- defineBuiltIn(AsyncIteratorPrototype, ASYNC_ITERATOR, function () {
- return this;
- });
-}
+// `Object.{ entries, values }` methods implementation
+var createMethod = function (TO_ENTRIES) {
+ return function (it) {
+ var O = toIndexedObject(it);
+ var keys = objectKeys(O);
+ var IE_WORKAROUND = IE_BUG && objectGetPrototypeOf(O) === null;
+ var length = keys.length;
+ var i = 0;
+ var result = [];
+ var key;
+ while (length > i) {
+ key = keys[i++];
+ if (!DESCRIPTORS || (IE_WORKAROUND ? key in O : propertyIsEnumerable(O, key))) {
+ push(result, TO_ENTRIES ? [key, O[key]] : O[key]);
+ }
+ }
+ return result;
+ };
+};
-module.exports = AsyncIteratorPrototype;
+module.exports = {
+ // `Object.entries` method
+ // https://tc39.es/ecma262/#sec-object.entries
+ entries: createMethod(true),
+ // `Object.values` method
+ // https://tc39.es/ecma262/#sec-object.values
+ values: createMethod(false)
+};
/***/ }),
-/* 223 */
+/* 233 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var commonAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
-var base64Alphabet = commonAlphabet + '+/';
-var base64UrlAlphabet = commonAlphabet + '-_';
+var call = __webpack_require__(4);
+var isCallable = __webpack_require__(14);
+var isObject = __webpack_require__(8);
-var inverse = function (characters) {
- // TODO: use `Object.create(null)` in `core-js@4`
- var result = {};
- var index = 0;
- for (; index < 64; index++) result[characters.charAt(index)] = index;
- return result;
-};
+var $TypeError = TypeError;
-module.exports = {
- i2c: base64Alphabet,
- c2i: inverse(base64Alphabet),
- i2cUrl: base64UrlAlphabet,
- c2iUrl: inverse(base64UrlAlphabet)
+// `OrdinaryToPrimitive` abstract operation
+// https://tc39.es/ecma262/#sec-ordinarytoprimitive
+module.exports = function (input, pref) {
+ var fn, val;
+ if (pref === 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
+ if (isCallable(fn = input.valueOf) && !isObject(val = call(fn, input))) return val;
+ if (pref !== 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
+ throw new $TypeError("Can't convert object to primitive value");
};
/***/ }),
-/* 224 */
+/* 234 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var create = __webpack_require__(62);
-var defineBuiltInAccessor = __webpack_require__(55);
-var defineBuiltIns = __webpack_require__(88);
-var bind = __webpack_require__(75);
-var anInstance = __webpack_require__(71);
-var isNullOrUndefined = __webpack_require__(89);
-var iterate = __webpack_require__(56);
-var defineIterator = __webpack_require__(190);
-var createIterResultObject = __webpack_require__(96);
-var setSpecies = __webpack_require__(122);
-var DESCRIPTORS = __webpack_require__(38);
-var fastKey = __webpack_require__(102).fastKey;
-var InternalStateModule = __webpack_require__(53);
+var anObject = __webpack_require__(5);
+var isObject = __webpack_require__(8);
+var newPromiseCapability = __webpack_require__(58);
-var setInternalState = InternalStateModule.set;
-var internalStateGetterFor = InternalStateModule.getterFor;
+module.exports = function (C, x) {
+ anObject(C);
+ if (isObject(x) && x.constructor === C) return x;
+ var promiseCapability = newPromiseCapability.f(C);
+ var resolve = promiseCapability.resolve;
+ resolve(x);
+ return promiseCapability.promise;
+};
-module.exports = {
- getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
- var Constructor = wrapper(function (that, iterable) {
- anInstance(that, Prototype);
- setInternalState(that, {
- type: CONSTRUCTOR_NAME,
- index: create(null),
- first: null,
- last: null,
- size: 0
- });
- if (!DESCRIPTORS) that.size = 0;
- if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
- });
- var Prototype = Constructor.prototype;
+/***/ }),
+/* 235 */
+/***/ (function(module, exports, __webpack_require__) {
- var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
+"use strict";
- var define = function (that, key, value) {
- var state = getInternalState(that);
- var entry = getEntry(that, key);
- var previous, index;
- // change existing entry
- if (entry) {
- entry.value = value;
- // create new entry
- } else {
- state.last = entry = {
- index: index = fastKey(key, true),
- key: key,
- value: value,
- previous: previous = state.last,
- next: null,
- removed: false
- };
- if (!state.first) state.first = entry;
- if (previous) previous.next = entry;
- if (DESCRIPTORS) state.size++;
- else that.size++;
- // add to index
- if (index !== 'F') state.index[index] = entry;
- } return that;
- };
+var defineProperty = __webpack_require__(19).f;
- var getEntry = function (that, key) {
- var state = getInternalState(that);
- // fast case
- var index = fastKey(key);
- var entry;
- if (index !== 'F') return state.index[index];
- // frozen object case
- for (entry = state.first; entry; entry = entry.next) {
- if (entry.key === key) return entry;
- }
- };
+module.exports = function (Target, Source, key) {
+ key in Target || defineProperty(Target, key, {
+ configurable: true,
+ get: function () { return Source[key]; },
+ set: function (it) { Source[key] = it; }
+ });
+};
- defineBuiltIns(Prototype, {
- // `{ Map, Set }.prototype.clear()` methods
- // https://tc39.es/ecma262/#sec-map.prototype.clear
- // https://tc39.es/ecma262/#sec-set.prototype.clear
- clear: function clear() {
- var that = this;
- var state = getInternalState(that);
- var entry = state.first;
- while (entry) {
- entry.removed = true;
- if (entry.previous) entry.previous = entry.previous.next = null;
- entry = entry.next;
- }
- state.first = state.last = null;
- state.index = create(null);
- if (DESCRIPTORS) state.size = 0;
- else that.size = 0;
- },
- // `{ Map, Set }.prototype.delete(key)` methods
- // https://tc39.es/ecma262/#sec-map.prototype.delete
- // https://tc39.es/ecma262/#sec-set.prototype.delete
- 'delete': function (key) {
- var that = this;
- var state = getInternalState(that);
- var entry = getEntry(that, key);
- if (entry) {
- var next = entry.next;
- var prev = entry.previous;
- delete state.index[entry.index];
- entry.removed = true;
- if (prev) prev.next = next;
- if (next) next.previous = prev;
- if (state.first === entry) state.first = next;
- if (state.last === entry) state.last = prev;
- if (DESCRIPTORS) state.size--;
- else that.size--;
- } return !!entry;
- },
- // `{ Map, Set }.prototype.forEach(callbackfn, thisArg = undefined)` methods
- // https://tc39.es/ecma262/#sec-map.prototype.foreach
- // https://tc39.es/ecma262/#sec-set.prototype.foreach
- forEach: function forEach(callbackfn /* , that = undefined */) {
- var state = getInternalState(this);
- var boundFunction = bind(callbackfn, arguments.length > 1 ? arguments[1] : undefined);
- var entry;
- while (entry = entry ? entry.next : state.first) {
- boundFunction(entry.value, entry.key, this);
- // revert to the last existing entry
- while (entry && entry.removed) entry = entry.previous;
- }
- },
- // `{ Map, Set}.prototype.has(key)` methods
- // https://tc39.es/ecma262/#sec-map.prototype.has
- // https://tc39.es/ecma262/#sec-set.prototype.has
- has: function has(key) {
- return !!getEntry(this, key);
- }
- });
- defineBuiltIns(Prototype, IS_MAP ? {
- // `Map.prototype.get(key)` method
- // https://tc39.es/ecma262/#sec-map.prototype.get
- get: function get(key) {
- var entry = getEntry(this, key);
- return entry && entry.value;
- },
- // `Map.prototype.set(key, value)` method
- // https://tc39.es/ecma262/#sec-map.prototype.set
- set: function set(key, value) {
- return define(this, key === 0 ? 0 : key, value);
- }
- } : {
- // `Set.prototype.add(value)` method
- // https://tc39.es/ecma262/#sec-set.prototype.add
- add: function add(value) {
- return define(this, value = value === 0 ? 0 : value, value);
- }
- });
- if (DESCRIPTORS) defineBuiltInAccessor(Prototype, 'size', {
- configurable: true,
- get: function () {
- return getInternalState(this).size;
- }
- });
- return Constructor;
- },
- setStrong: function (Constructor, CONSTRUCTOR_NAME, IS_MAP) {
- var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator';
- var getInternalCollectionState = internalStateGetterFor(CONSTRUCTOR_NAME);
- var getInternalIteratorState = internalStateGetterFor(ITERATOR_NAME);
- // `{ Map, Set }.prototype.{ keys, values, entries, @@iterator }()` methods
- // https://tc39.es/ecma262/#sec-map.prototype.entries
- // https://tc39.es/ecma262/#sec-map.prototype.keys
- // https://tc39.es/ecma262/#sec-map.prototype.values
- // https://tc39.es/ecma262/#sec-map.prototype-@@iterator
- // https://tc39.es/ecma262/#sec-set.prototype.entries
- // https://tc39.es/ecma262/#sec-set.prototype.keys
- // https://tc39.es/ecma262/#sec-set.prototype.values
- // https://tc39.es/ecma262/#sec-set.prototype-@@iterator
- defineIterator(Constructor, CONSTRUCTOR_NAME, function (iterated, kind) {
- setInternalState(this, {
- type: ITERATOR_NAME,
- target: iterated,
- state: getInternalCollectionState(iterated),
- kind: kind,
- last: null
- });
- }, function () {
- var state = getInternalIteratorState(this);
- var kind = state.kind;
- var entry = state.last;
- // revert to the last existing entry
- while (entry && entry.removed) entry = entry.previous;
- // get next entry
- if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) {
- // or finish the iteration
- state.target = null;
- return createIterResultObject(undefined, true);
- }
- // return step by kind
- if (kind === 'keys') return createIterResultObject(entry.key, false);
- if (kind === 'values') return createIterResultObject(entry.value, false);
- return createIterResultObject([entry.key, entry.value], false);
- }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);
+/***/ }),
+/* 236 */
+/***/ (function(module, exports, __webpack_require__) {
- // `{ Map, Set }.prototype[@@species]` accessors
- // https://tc39.es/ecma262/#sec-get-map-@@species
- // https://tc39.es/ecma262/#sec-get-set-@@species
- setSpecies(CONSTRUCTOR_NAME);
+"use strict";
+
+var Queue = function () {
+ this.head = null;
+ this.tail = null;
+};
+
+Queue.prototype = {
+ add: function (item) {
+ var entry = { item: item, next: null };
+ var tail = this.tail;
+ if (tail) tail.next = entry;
+ else this.head = entry;
+ this.tail = entry;
+ },
+ get: function () {
+ var entry = this.head;
+ if (entry) {
+ var next = this.head = entry.next;
+ if (next === null) this.tail = null;
+ return entry.item;
+ }
}
};
+module.exports = Queue;
+
/***/ }),
-/* 225 */
+/* 237 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
-var defineBuiltIns = __webpack_require__(88);
-var getWeakData = __webpack_require__(102).getWeakData;
-var anInstance = __webpack_require__(71);
-var anObject = __webpack_require__(37);
-var isNullOrUndefined = __webpack_require__(89);
-var isObject = __webpack_require__(40);
-var iterate = __webpack_require__(56);
-var ArrayIterationModule = __webpack_require__(58);
-var hasOwn = __webpack_require__(45);
-var InternalStateModule = __webpack_require__(53);
-
-var setInternalState = InternalStateModule.set;
-var internalStateGetterFor = InternalStateModule.getterFor;
-var find = ArrayIterationModule.find;
-var findIndex = ArrayIterationModule.findIndex;
-var splice = uncurryThis([].splice);
-var id = 0;
-
-// fallback for uncaught frozen keys
-var uncaughtFrozenStore = function (state) {
- return state.frozen || (state.frozen = new UncaughtFrozenStore());
-};
-
-var UncaughtFrozenStore = function () {
- this.entries = [];
-};
+var globalThis = __webpack_require__(3);
+var fails = __webpack_require__(1);
-var findUncaughtFrozen = function (store, key) {
- return find(store.entries, function (it) {
- return it[0] === key;
- });
-};
+// babel-minify and Closure Compiler transpiles RegExp('.', 'd') -> /./d and it causes SyntaxError
+var RegExp = globalThis.RegExp;
-UncaughtFrozenStore.prototype = {
- get: function (key) {
- var entry = findUncaughtFrozen(this, key);
- if (entry) return entry[1];
- },
- has: function (key) {
- return !!findUncaughtFrozen(this, key);
- },
- set: function (key, value) {
- var entry = findUncaughtFrozen(this, key);
- if (entry) entry[1] = value;
- else this.entries.push([key, value]);
- },
- 'delete': function (key) {
- var index = findIndex(this.entries, function (it) {
- return it[0] === key;
- });
- if (~index) splice(this.entries, index, 1);
- return !!~index;
+var FLAGS_GETTER_IS_CORRECT = !fails(function () {
+ var INDICES_SUPPORT = true;
+ try {
+ RegExp('.', 'd');
+ } catch (error) {
+ INDICES_SUPPORT = false;
}
-};
-module.exports = {
- getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
- var Constructor = wrapper(function (that, iterable) {
- anInstance(that, Prototype);
- setInternalState(that, {
- type: CONSTRUCTOR_NAME,
- id: id++,
- frozen: null
- });
- if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
- });
+ var O = {};
+ // modern V8 bug
+ var calls = '';
+ var expected = INDICES_SUPPORT ? 'dgimsy' : 'gimsy';
- var Prototype = Constructor.prototype;
+ var addGetter = function (key, chr) {
+ // eslint-disable-next-line es/no-object-defineproperty -- safe
+ Object.defineProperty(O, key, { get: function () {
+ calls += chr;
+ return true;
+ } });
+ };
- var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
+ var pairs = {
+ dotAll: 's',
+ global: 'g',
+ ignoreCase: 'i',
+ multiline: 'm',
+ sticky: 'y'
+ };
- var define = function (that, key, value) {
- var state = getInternalState(that);
- var data = getWeakData(anObject(key), true);
- if (data === true) uncaughtFrozenStore(state).set(key, value);
- else data[state.id] = value;
- return that;
- };
+ if (INDICES_SUPPORT) pairs.hasIndices = 'd';
- defineBuiltIns(Prototype, {
- // `{ WeakMap, WeakSet }.prototype.delete(key)` methods
- // https://tc39.es/ecma262/#sec-weakmap.prototype.delete
- // https://tc39.es/ecma262/#sec-weakset.prototype.delete
- 'delete': function (key) {
- var state = getInternalState(this);
- if (!isObject(key)) return false;
- var data = getWeakData(key);
- if (data === true) return uncaughtFrozenStore(state)['delete'](key);
- return data && hasOwn(data, state.id) && delete data[state.id];
- },
- // `{ WeakMap, WeakSet }.prototype.has(key)` methods
- // https://tc39.es/ecma262/#sec-weakmap.prototype.has
- // https://tc39.es/ecma262/#sec-weakset.prototype.has
- has: function has(key) {
- var state = getInternalState(this);
- if (!isObject(key)) return false;
- var data = getWeakData(key);
- if (data === true) return uncaughtFrozenStore(state).has(key);
- return data && hasOwn(data, state.id);
- }
- });
+ for (var key in pairs) addGetter(key, pairs[key]);
- defineBuiltIns(Prototype, IS_MAP ? {
- // `WeakMap.prototype.get(key)` method
- // https://tc39.es/ecma262/#sec-weakmap.prototype.get
- get: function get(key) {
- var state = getInternalState(this);
- if (isObject(key)) {
- var data = getWeakData(key);
- if (data === true) return uncaughtFrozenStore(state).get(key);
- if (data) return data[state.id];
- }
- },
- // `WeakMap.prototype.set(key, value)` method
- // https://tc39.es/ecma262/#sec-weakmap.prototype.set
- set: function set(key, value) {
- return define(this, key, value);
- }
- } : {
- // `WeakSet.prototype.add(value)` method
- // https://tc39.es/ecma262/#sec-weakset.prototype.add
- add: function add(value) {
- return define(this, value, true);
- }
- });
+ // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+ var result = Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call(O);
- return Constructor;
- }
-};
+ return result !== expected || calls !== expected;
+});
+
+module.exports = { correct: FLAGS_GETTER_IS_CORRECT };
/***/ }),
-/* 226 */
+/* 238 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var getBuiltInNodeModule = __webpack_require__(237);
-var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__(204);
+var fails = __webpack_require__(1);
+var globalThis = __webpack_require__(3);
-var structuredClone = globalThis.structuredClone;
-var $ArrayBuffer = globalThis.ArrayBuffer;
-var $MessageChannel = globalThis.MessageChannel;
-var detach = false;
-var WorkerThreads, channel, buffer, $detach;
+// babel-minify and Closure Compiler transpiles RegExp('(?b)', 'g') -> /(?b)/g and it causes SyntaxError
+var $RegExp = globalThis.RegExp;
-if (PROPER_STRUCTURED_CLONE_TRANSFER) {
- detach = function (transferable) {
- structuredClone(transferable, { transfer: [transferable] });
- };
-} else if ($ArrayBuffer) try {
- if (!$MessageChannel) {
- WorkerThreads = getBuiltInNodeModule('worker_threads');
- if (WorkerThreads) $MessageChannel = WorkerThreads.MessageChannel;
- }
+module.exports = fails(function () {
+ var re = $RegExp('(?b)', 'g');
+ return re.exec('b').groups.a !== 'b' ||
+ 'b'.replace(re, '$c') !== 'bc';
+});
- if ($MessageChannel) {
- channel = new $MessageChannel();
- buffer = new $ArrayBuffer(2);
- $detach = function (transferable) {
- channel.port1.postMessage(null, [transferable]);
- };
+/***/ }),
+/* 239 */
+/***/ (function(module, exports, __webpack_require__) {
- if (buffer.byteLength === 2) {
- $detach(buffer);
- if (buffer.byteLength === 0) detach = $detach;
- }
- }
-} catch (error) { /* empty */ }
+"use strict";
-module.exports = detach;
+var globalThis = __webpack_require__(3);
+var DESCRIPTORS = __webpack_require__(6);
+
+// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
+var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
+// Avoid NodeJS experimental warning
+module.exports = function (name) {
+ if (!DESCRIPTORS) return globalThis[name];
+ var descriptor = getOwnPropertyDescriptor(globalThis, name);
+ return descriptor && descriptor.value;
+};
/***/ }),
-/* 227 */
+/* 240 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-module.exports = {
- IndexSizeError: { s: 'INDEX_SIZE_ERR', c: 1, m: 1 },
- DOMStringSizeError: { s: 'DOMSTRING_SIZE_ERR', c: 2, m: 0 },
- HierarchyRequestError: { s: 'HIERARCHY_REQUEST_ERR', c: 3, m: 1 },
- WrongDocumentError: { s: 'WRONG_DOCUMENT_ERR', c: 4, m: 1 },
- InvalidCharacterError: { s: 'INVALID_CHARACTER_ERR', c: 5, m: 1 },
- NoDataAllowedError: { s: 'NO_DATA_ALLOWED_ERR', c: 6, m: 0 },
- NoModificationAllowedError: { s: 'NO_MODIFICATION_ALLOWED_ERR', c: 7, m: 1 },
- NotFoundError: { s: 'NOT_FOUND_ERR', c: 8, m: 1 },
- NotSupportedError: { s: 'NOT_SUPPORTED_ERR', c: 9, m: 1 },
- InUseAttributeError: { s: 'INUSE_ATTRIBUTE_ERR', c: 10, m: 1 },
- InvalidStateError: { s: 'INVALID_STATE_ERR', c: 11, m: 1 },
- SyntaxError: { s: 'SYNTAX_ERR', c: 12, m: 1 },
- InvalidModificationError: { s: 'INVALID_MODIFICATION_ERR', c: 13, m: 1 },
- NamespaceError: { s: 'NAMESPACE_ERR', c: 14, m: 1 },
- InvalidAccessError: { s: 'INVALID_ACCESS_ERR', c: 15, m: 1 },
- ValidationError: { s: 'VALIDATION_ERR', c: 16, m: 0 },
- TypeMismatchError: { s: 'TYPE_MISMATCH_ERR', c: 17, m: 1 },
- SecurityError: { s: 'SECURITY_ERR', c: 18, m: 1 },
- NetworkError: { s: 'NETWORK_ERR', c: 19, m: 1 },
- AbortError: { s: 'ABORT_ERR', c: 20, m: 1 },
- URLMismatchError: { s: 'URL_MISMATCH_ERR', c: 21, m: 1 },
- QuotaExceededError: { s: 'QUOTA_EXCEEDED_ERR', c: 22, m: 1 },
- TimeoutError: { s: 'TIMEOUT_ERR', c: 23, m: 1 },
- InvalidNodeTypeError: { s: 'INVALID_NODE_TYPE_ERR', c: 24, m: 1 },
- DataCloneError: { s: 'DATA_CLONE_ERR', c: 25, m: 1 }
+// `SameValue` abstract operation
+// https://tc39.es/ecma262/#sec-samevalue
+// eslint-disable-next-line es/no-object-is -- safe
+module.exports = Object.is || function is(x, y) {
+ // eslint-disable-next-line no-self-compare -- NaN check
+ return x === y ? x !== 0 || 1 / x === 1 / y : x !== x && y !== y;
};
/***/ }),
-/* 228 */
+/* 241 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-// iterable DOM collections
-// flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods
-module.exports = {
- CSSRuleList: 0,
- CSSStyleDeclaration: 0,
- CSSValueList: 0,
- ClientRectList: 0,
- DOMRectList: 0,
- DOMStringList: 0,
- DOMTokenList: 1,
- DataTransferItemList: 0,
- FileList: 0,
- HTMLAllCollection: 0,
- HTMLCollection: 0,
- HTMLFormElement: 0,
- HTMLSelectElement: 0,
- MediaList: 0,
- MimeTypeArray: 0,
- NamedNodeMap: 0,
- NodeList: 1,
- PaintRequestList: 0,
- Plugin: 0,
- PluginArray: 0,
- SVGLengthList: 0,
- SVGNumberList: 0,
- SVGPathSegList: 0,
- SVGPointList: 0,
- SVGStringList: 0,
- SVGTransformList: 0,
- SourceBufferList: 0,
- StyleSheetList: 0,
- TextTrackCueList: 0,
- TextTrackList: 0,
- TouchList: 0
+// Should get iterator record of a set-like object before cloning this
+// https://bugs.webkit.org/show_bug.cgi?id=289430
+module.exports = function (METHOD_NAME) {
+ try {
+ // eslint-disable-next-line es/no-set -- needed for test
+ var baseSet = new Set();
+ var setLike = {
+ size: 0,
+ has: function () { return true; },
+ keys: function () {
+ // eslint-disable-next-line es/no-object-defineproperty -- needed for test
+ return Object.defineProperty({}, 'next', {
+ get: function () {
+ baseSet.clear();
+ baseSet.add(4);
+ return function () {
+ return { done: true };
+ };
+ }
+ });
+ }
+ };
+ var result = baseSet[METHOD_NAME](setLike);
+
+ return result.size !== 1 || result.values().next().value !== 4;
+ } catch (error) {
+ return false;
+ }
};
/***/ }),
-/* 229 */
+/* 242 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-// in old WebKit versions, `element.classList` is not an instance of global `DOMTokenList`
-var documentCreateElement = __webpack_require__(148);
-
-var classList = documentCreateElement('span').classList;
-var DOMTokenListPrototype = classList && classList.constructor && classList.constructor.prototype;
+// https://github.com/zloirock/core-js/issues/280
+var userAgent = __webpack_require__(51);
-module.exports = DOMTokenListPrototype === Object.prototype ? undefined : DOMTokenListPrototype;
+module.exports = /Version\/10(?:\.\d+){1,2}(?: [\w./]+)?(?: Mobile\/\w+)? Safari\//.test(userAgent);
/***/ }),
-/* 230 */
+/* 243 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var userAgent = __webpack_require__(83);
-
-var firefox = userAgent.match(/firefox\/(\d+)/i);
+var $trimEnd = __webpack_require__(93).end;
+var forcedStringTrimMethod = __webpack_require__(174);
-module.exports = !!firefox && +firefox[1];
+// `String.prototype.{ trimEnd, trimRight }` method
+// https://tc39.es/ecma262/#sec-string.prototype.trimend
+// https://tc39.es/ecma262/#String.prototype.trimright
+module.exports = forcedStringTrimMethod('trimEnd') ? function trimEnd() {
+ return $trimEnd(this);
+// eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe
+} : ''.trimEnd;
/***/ }),
-/* 231 */
+/* 244 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var UA = __webpack_require__(83);
+var $trimStart = __webpack_require__(93).start;
+var forcedStringTrimMethod = __webpack_require__(174);
-module.exports = /MSIE|Trident/.test(UA);
+// `String.prototype.{ trimStart, trimLeft }` method
+// https://tc39.es/ecma262/#sec-string.prototype.trimstart
+// https://tc39.es/ecma262/#String.prototype.trimleft
+module.exports = forcedStringTrimMethod('trimStart') ? function trimStart() {
+ return $trimStart(this);
+// eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe
+} : ''.trimStart;
/***/ }),
-/* 232 */
+/* 245 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var userAgent = __webpack_require__(83);
+var call = __webpack_require__(4);
+var getBuiltIn = __webpack_require__(11);
+var wellKnownSymbol = __webpack_require__(7);
+var defineBuiltIn = __webpack_require__(17);
-// eslint-disable-next-line redos/no-vulnerable -- safe
-module.exports = /(?:ipad|iphone|ipod).*applewebkit/i.test(userAgent);
+module.exports = function () {
+ var Symbol = getBuiltIn('Symbol');
+ var SymbolPrototype = Symbol && Symbol.prototype;
+ var valueOf = SymbolPrototype && SymbolPrototype.valueOf;
+ var TO_PRIMITIVE = wellKnownSymbol('toPrimitive');
+
+ if (SymbolPrototype && !SymbolPrototype[TO_PRIMITIVE]) {
+ // `Symbol.prototype[@@toPrimitive]` method
+ // https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
+ // eslint-disable-next-line no-unused-vars -- required for .length
+ defineBuiltIn(SymbolPrototype, TO_PRIMITIVE, function (hint) {
+ return call(valueOf, this);
+ }, { arity: 1 });
+ }
+};
/***/ }),
-/* 233 */
+/* 246 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var fails = __webpack_require__(33);
-var createPropertyDescriptor = __webpack_require__(73);
+var NATIVE_SYMBOL = __webpack_require__(94);
-module.exports = !fails(function () {
- var error = new Error('a');
- if (!('stack' in error)) return true;
- // eslint-disable-next-line es/no-object-defineproperty -- safe
- Object.defineProperty(error, 'stack', createPropertyDescriptor(1, 7));
- return error.stack !== 7;
-});
+/* eslint-disable es/no-symbol -- safe */
+module.exports = NATIVE_SYMBOL && !!Symbol['for'] && !!Symbol.keyFor;
/***/ }),
-/* 234 */
+/* 247 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var DESCRIPTORS = __webpack_require__(38);
-var fails = __webpack_require__(33);
-var anObject = __webpack_require__(37);
-var normalizeStringArgument = __webpack_require__(118);
-
-var nativeErrorToString = Error.prototype.toString;
+var toPositiveInteger = __webpack_require__(177);
-var INCORRECT_TO_STRING = fails(function () {
- if (DESCRIPTORS) {
- // Chrome 32- incorrectly call accessor
- // eslint-disable-next-line es/no-object-create, es/no-object-defineproperty -- safe
- var object = Object.create(Object.defineProperty({}, 'name', { get: function () {
- return this === object;
- } }));
- if (nativeErrorToString.call(object) !== 'true') return true;
- }
- // FF10- does not properly handle non-strings
- return nativeErrorToString.call({ message: 1, name: 2 }) !== '2: 1'
- // IE8 does not properly handle defaults
- || nativeErrorToString.call({}) !== 'Error';
-});
+var $RangeError = RangeError;
-module.exports = INCORRECT_TO_STRING ? function toString() {
- var O = anObject(this);
- var name = normalizeStringArgument(O.name, 'Error');
- var message = normalizeStringArgument(O.message);
- return !name ? message : !message ? name : name + ': ' + message;
-} : nativeErrorToString;
+module.exports = function (it, BYTES) {
+ var offset = toPositiveInteger(it);
+ if (offset % BYTES) throw new $RangeError('Wrong offset');
+ return offset;
+};
/***/ }),
-/* 235 */
+/* 248 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isArray = __webpack_require__(93);
-var lengthOfArrayLike = __webpack_require__(50);
-var doesNotExceedSafeInteger = __webpack_require__(97);
-var bind = __webpack_require__(75);
-
-// `FlattenIntoArray` abstract operation
-// https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
-var flattenIntoArray = function (target, original, source, sourceLen, start, depth, mapper, thisArg) {
- var targetIndex = start;
- var sourceIndex = 0;
- var mapFn = mapper ? bind(mapper, thisArg) : false;
- var element, elementLen;
-
- while (sourceIndex < sourceLen) {
- if (sourceIndex in source) {
- element = mapFn ? mapFn(source[sourceIndex], sourceIndex, original) : source[sourceIndex];
-
- if (depth > 0 && isArray(element)) {
- elementLen = lengthOfArrayLike(element);
- targetIndex = flattenIntoArray(target, original, element, elementLen, targetIndex, depth - 1) - 1;
- } else {
- doesNotExceedSafeInteger(targetIndex + 1);
- target[targetIndex] = element;
- }
+var bind = __webpack_require__(43);
+var call = __webpack_require__(4);
+var aConstructor = __webpack_require__(144);
+var toObject = __webpack_require__(15);
+var lengthOfArrayLike = __webpack_require__(18);
+var getIterator = __webpack_require__(83);
+var getIteratorMethod = __webpack_require__(68);
+var isArrayIteratorMethod = __webpack_require__(158);
+var isBigIntArray = __webpack_require__(215);
+var aTypedArrayConstructor = __webpack_require__(12).aTypedArrayConstructor;
+var toBigInt = __webpack_require__(176);
- targetIndex++;
+module.exports = function from(source /* , mapfn, thisArg */) {
+ var C = aConstructor(this);
+ var O = toObject(source);
+ var argumentsLength = arguments.length;
+ var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
+ var mapping = mapfn !== undefined;
+ var iteratorMethod = getIteratorMethod(O);
+ var i, length, result, thisIsBigIntArray, value, step, iterator, next;
+ if (iteratorMethod && !isArrayIteratorMethod(iteratorMethod)) {
+ iterator = getIterator(O, iteratorMethod);
+ next = iterator.next;
+ O = [];
+ while (!(step = call(next, iterator)).done) {
+ O.push(step.value);
}
- sourceIndex++;
}
- return targetIndex;
+ if (mapping && argumentsLength > 2) {
+ mapfn = bind(mapfn, arguments[2]);
+ }
+ length = lengthOfArrayLike(O);
+ result = new (aTypedArrayConstructor(C))(length);
+ thisIsBigIntArray = isBigIntArray(result);
+ for (i = 0; length > i; i++) {
+ value = mapping ? mapfn(O[i], i) : O[i];
+ // FF30- typed arrays doesn't properly convert objects to typed array values
+ result[i] = thisIsBigIntArray ? toBigInt(value) : +value;
+ }
+ return result;
};
-module.exports = flattenIntoArray;
-
/***/ }),
-/* 236 */
+/* 249 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
-var aCallable = __webpack_require__(42);
-var isObject = __webpack_require__(40);
-var hasOwn = __webpack_require__(45);
-var arraySlice = __webpack_require__(78);
-var NATIVE_BIND = __webpack_require__(130);
+/* eslint-disable es/no-symbol -- required for testing */
+var NATIVE_SYMBOL = __webpack_require__(94);
-var $Function = Function;
-var concat = uncurryThis([].concat);
-var join = uncurryThis([].join);
-var factories = {};
+module.exports = NATIVE_SYMBOL &&
+ !Symbol.sham &&
+ typeof Symbol.iterator == 'symbol';
-var construct = function (C, argsLength, args) {
- if (!hasOwn(factories, argsLength)) {
- var list = [];
- var i = 0;
- for (; i < argsLength; i++) list[i] = 'a[' + i + ']';
- factories[argsLength] = $Function('C,a', 'return new C(' + join(list, ',') + ')');
- } return factories[argsLength](C, args);
-};
-// `Function.prototype.bind` method implementation
-// https://tc39.es/ecma262/#sec-function.prototype.bind
-// eslint-disable-next-line es/no-function-prototype-bind -- detection
-module.exports = NATIVE_BIND ? $Function.bind : function bind(that /* , ...args */) {
- var F = aCallable(this);
- var Prototype = F.prototype;
- var partArgs = arraySlice(arguments, 1);
- var boundFunction = function bound(/* args... */) {
- var args = concat(partArgs, arraySlice(arguments));
- return this instanceof boundFunction ? construct(F, args.length, args) : F.apply(that, args);
- };
- if (isObject(Prototype)) boundFunction.prototype = Prototype;
- return boundFunction;
-};
+/***/ }),
+/* 250 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+var DESCRIPTORS = __webpack_require__(6);
+var fails = __webpack_require__(1);
+
+// V8 ~ Chrome 36-
+// https://bugs.chromium.org/p/v8/issues/detail?id=3334
+module.exports = DESCRIPTORS && fails(function () {
+ // eslint-disable-next-line es/no-object-defineproperty -- required for testing
+ return Object.defineProperty(function () { /* empty */ }, 'prototype', {
+ value: 42,
+ writable: false
+ }).prototype !== 42;
+});
/***/ }),
-/* 237 */
+/* 251 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var IS_NODE = __webpack_require__(111);
+var globalThis = __webpack_require__(3);
+var isCallable = __webpack_require__(14);
-module.exports = function (name) {
- if (IS_NODE) {
- try {
- return globalThis.process.getBuiltinModule(name);
- } catch (error) { /* empty */ }
- try {
- // eslint-disable-next-line no-new-func -- safe
- return Function('return require("' + name + '")')();
- } catch (error) { /* empty */ }
- }
-};
+var WeakMap = globalThis.WeakMap;
+
+module.exports = isCallable(WeakMap) && /native code/.test(String(WeakMap));
/***/ }),
-/* 238 */
+/* 252 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
+var wellKnownSymbol = __webpack_require__(7);
-module.exports = function (CONSTRUCTOR, METHOD) {
- var Constructor = globalThis[CONSTRUCTOR];
- var Prototype = Constructor && Constructor.prototype;
- return Prototype && Prototype[METHOD];
-};
+exports.f = wellKnownSymbol;
/***/ }),
-/* 239 */
+/* 253 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var call = __webpack_require__(36);
-var anObject = __webpack_require__(37);
-var getIteratorDirect = __webpack_require__(65);
-var getIteratorMethod = __webpack_require__(99);
+var getBuiltIn = __webpack_require__(11);
+var hasOwn = __webpack_require__(13);
+var createNonEnumerableProperty = __webpack_require__(27);
+var isPrototypeOf = __webpack_require__(36);
+var setPrototypeOf = __webpack_require__(49);
+var copyConstructorProperties = __webpack_require__(79);
+var proxyAccessor = __webpack_require__(235);
+var inheritIfRequired = __webpack_require__(70);
+var normalizeStringArgument = __webpack_require__(87);
+var installErrorCause = __webpack_require__(214);
+var installErrorStack = __webpack_require__(156);
+var DESCRIPTORS = __webpack_require__(6);
+var IS_PURE = __webpack_require__(16);
-module.exports = function (obj, stringHandling) {
- if (!stringHandling || typeof obj !== 'string') anObject(obj);
- var method = getIteratorMethod(obj);
- return getIteratorDirect(anObject(method !== undefined ? call(method, obj) : obj));
+module.exports = function (FULL_NAME, wrapper, FORCED, IS_AGGREGATE_ERROR) {
+ var STACK_TRACE_LIMIT = 'stackTraceLimit';
+ var OPTIONS_POSITION = IS_AGGREGATE_ERROR ? 2 : 1;
+ var path = FULL_NAME.split('.');
+ var ERROR_NAME = path[path.length - 1];
+ var OriginalError = getBuiltIn.apply(null, path);
+
+ if (!OriginalError) return;
+
+ var OriginalErrorPrototype = OriginalError.prototype;
+
+ // V8 9.3- bug https://bugs.chromium.org/p/v8/issues/detail?id=12006
+ if (!IS_PURE && hasOwn(OriginalErrorPrototype, 'cause')) delete OriginalErrorPrototype.cause;
+
+ if (!FORCED) return OriginalError;
+
+ var BaseError = getBuiltIn('Error');
+
+ var WrappedError = wrapper(function (a, b) {
+ var message = normalizeStringArgument(IS_AGGREGATE_ERROR ? b : a, undefined);
+ var result = IS_AGGREGATE_ERROR ? new OriginalError(a) : new OriginalError();
+ if (message !== undefined) createNonEnumerableProperty(result, 'message', message);
+ installErrorStack(result, WrappedError, result.stack, 2);
+ if (this && isPrototypeOf(OriginalErrorPrototype, this)) inheritIfRequired(result, this, WrappedError);
+ if (arguments.length > OPTIONS_POSITION) installErrorCause(result, arguments[OPTIONS_POSITION]);
+ return result;
+ });
+
+ WrappedError.prototype = OriginalErrorPrototype;
+
+ if (ERROR_NAME !== 'Error') {
+ if (setPrototypeOf) setPrototypeOf(WrappedError, BaseError);
+ else copyConstructorProperties(WrappedError, BaseError, { name: true });
+ } else if (DESCRIPTORS && STACK_TRACE_LIMIT in OriginalError) {
+ proxyAccessor(WrappedError, OriginalError, STACK_TRACE_LIMIT);
+ proxyAccessor(WrappedError, OriginalError, 'prepareStackTrace');
+ }
+
+ copyConstructorProperties(WrappedError, OriginalError);
+
+ if (!IS_PURE) try {
+ // Safari 13- bug: WebAssembly errors does not have a proper `.name`
+ if (OriginalErrorPrototype.name !== ERROR_NAME) {
+ createNonEnumerableProperty(OriginalErrorPrototype, 'name', ERROR_NAME);
+ }
+ OriginalErrorPrototype.constructor = WrappedError;
+ } catch (error) { /* empty */ }
+
+ return WrappedError;
};
/***/ }),
-/* 240 */
+/* 254 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var uncurryThis = __webpack_require__(34);
-var toObject = __webpack_require__(47);
+var $ = __webpack_require__(0);
+var getBuiltIn = __webpack_require__(11);
+var apply = __webpack_require__(42);
+var call = __webpack_require__(4);
+var uncurryThis = __webpack_require__(2);
+var fails = __webpack_require__(1);
+var isCallable = __webpack_require__(14);
+var isSymbol = __webpack_require__(73);
+var arraySlice = __webpack_require__(46);
+var getReplacerFunction = __webpack_require__(294);
+var NATIVE_SYMBOL = __webpack_require__(94);
-var floor = Math.floor;
+var $String = String;
+var $stringify = getBuiltIn('JSON', 'stringify');
+var exec = uncurryThis(/./.exec);
var charAt = uncurryThis(''.charAt);
+var charCodeAt = uncurryThis(''.charCodeAt);
var replace = uncurryThis(''.replace);
-var stringSlice = uncurryThis(''.slice);
-// eslint-disable-next-line redos/no-vulnerable -- safe
-var SUBSTITUTION_SYMBOLS = /\$([$&'`]|\d{1,2}|<[^>]*>)/g;
-var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&'`]|\d{1,2})/g;
+var numberToString = uncurryThis(1.1.toString);
-// `GetSubstitution` abstract operation
-// https://tc39.es/ecma262/#sec-getsubstitution
-module.exports = function (matched, str, position, captures, namedCaptures, replacement) {
- var tailPos = position + matched.length;
- var m = captures.length;
- var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
- if (namedCaptures !== undefined) {
- namedCaptures = toObject(namedCaptures);
- symbols = SUBSTITUTION_SYMBOLS;
- }
- return replace(replacement, symbols, function (match, ch) {
- var capture;
- switch (charAt(ch, 0)) {
- case '$': return '$';
- case '&': return matched;
- case '`': return stringSlice(str, 0, position);
- case "'": return stringSlice(str, tailPos);
- case '<':
- capture = namedCaptures[stringSlice(ch, 1, -1)];
- break;
- default: // \d\d?
- var n = +ch;
- if (n === 0) return match;
- if (n > m) {
- var f = floor(n / 10);
- if (f === 0) return match;
- if (f <= m) return captures[f - 1] === undefined ? charAt(ch, 1) : captures[f - 1] + charAt(ch, 1);
- return match;
- }
- capture = captures[n - 1];
+var tester = /[\uD800-\uDFFF]/g;
+var low = /^[\uD800-\uDBFF]$/;
+var hi = /^[\uDC00-\uDFFF]$/;
+
+var WRONG_SYMBOLS_CONVERSION = !NATIVE_SYMBOL || fails(function () {
+ var symbol = getBuiltIn('Symbol')('stringify detection');
+ // MS Edge converts symbol values to JSON as {}
+ return $stringify([symbol]) !== '[null]'
+ // WebKit converts symbol values to JSON as null
+ || $stringify({ a: symbol }) !== '{}'
+ // V8 throws on boxed symbols
+ || $stringify(Object(symbol)) !== '{}';
+});
+
+// https://github.com/tc39/proposal-well-formed-stringify
+var ILL_FORMED_UNICODE = fails(function () {
+ return $stringify('\uDF06\uD834') !== '"\\udf06\\ud834"'
+ || $stringify('\uDEAD') !== '"\\udead"';
+});
+
+var stringifyWithSymbolsFix = function (it, replacer) {
+ var args = arraySlice(arguments);
+ var $replacer = getReplacerFunction(replacer);
+ if (!isCallable($replacer) && (it === undefined || isSymbol(it))) return; // IE8 returns string on undefined
+ args[1] = function (key, value) {
+ // some old implementations (like WebKit) could pass numbers as keys
+ if (isCallable($replacer)) value = call($replacer, this, $String(key), value);
+ if (!isSymbol(value)) return value;
+ };
+ return apply($stringify, null, args);
+};
+
+var fixIllFormed = function (match, offset, string) {
+ var prev = charAt(string, offset - 1);
+ var next = charAt(string, offset + 1);
+ if ((exec(low, match) && !exec(hi, next)) || (exec(hi, match) && !exec(low, prev))) {
+ return '\\u' + numberToString(charCodeAt(match, 0), 16);
+ } return match;
+};
+
+if ($stringify) {
+ // `JSON.stringify` method
+ // https://tc39.es/ecma262/#sec-json.stringify
+ $({ target: 'JSON', stat: true, arity: 3, forced: WRONG_SYMBOLS_CONVERSION || ILL_FORMED_UNICODE }, {
+ // eslint-disable-next-line no-unused-vars -- required for `.length`
+ stringify: function stringify(it, replacer, space) {
+ var args = arraySlice(arguments);
+ var result = apply(WRONG_SYMBOLS_CONVERSION ? stringifyWithSymbolsFix : $stringify, null, args);
+ return ILL_FORMED_UNICODE && typeof result == 'string' ? replace(result, tester, fixIllFormed) : result;
}
- return capture === undefined ? '' : capture;
});
-};
+}
/***/ }),
-/* 241 */
+/* 255 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var getBuiltIn = __webpack_require__(43);
+var $ = __webpack_require__(0);
+var uncurryThis = __webpack_require__(2);
+var toAbsoluteIndex = __webpack_require__(59);
-module.exports = getBuiltIn('document', 'documentElement');
+var $RangeError = RangeError;
+var fromCharCode = String.fromCharCode;
+// eslint-disable-next-line es/no-string-fromcodepoint -- required for testing
+var $fromCodePoint = String.fromCodePoint;
+var join = uncurryThis([].join);
+
+// length should be 1, old FF problem
+var INCORRECT_LENGTH = !!$fromCodePoint && $fromCodePoint.length !== 1;
+
+// `String.fromCodePoint` method
+// https://tc39.es/ecma262/#sec-string.fromcodepoint
+$({ target: 'String', stat: true, arity: 1, forced: INCORRECT_LENGTH }, {
+ // eslint-disable-next-line no-unused-vars -- required for `.length`
+ fromCodePoint: function fromCodePoint(x) {
+ var elements = [];
+ var length = arguments.length;
+ var i = 0;
+ var code;
+ while (length > i) {
+ code = +arguments[i++];
+ if (toAbsoluteIndex(code, 0x10FFFF) !== code) throw new $RangeError(code + ' is not a valid code point');
+ elements[i] = code < 0x10000
+ ? fromCharCode(code)
+ : fromCharCode(((code -= 0x10000) >> 10) + 0xD800, code % 0x400 + 0xDC00);
+ } return join(elements, '');
+ }
+});
/***/ }),
-/* 242 */
+/* 256 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var DESCRIPTORS = __webpack_require__(38);
-var fails = __webpack_require__(33);
-var createElement = __webpack_require__(148);
+var charAt = __webpack_require__(134).charAt;
+var toString = __webpack_require__(9);
+var InternalStateModule = __webpack_require__(21);
+var defineIterator = __webpack_require__(161);
+var createIterResultObject = __webpack_require__(65);
-// Thanks to IE8 for its funny defineProperty
-module.exports = !DESCRIPTORS && !fails(function () {
- // eslint-disable-next-line es/no-object-defineproperty -- required for testing
- return Object.defineProperty(createElement('div'), 'a', {
- get: function () { return 7; }
- }).a !== 7;
+var STRING_ITERATOR = 'String Iterator';
+var setInternalState = InternalStateModule.set;
+var getInternalState = InternalStateModule.getterFor(STRING_ITERATOR);
+
+// `String.prototype[@@iterator]` method
+// https://tc39.es/ecma262/#sec-string.prototype-@@iterator
+defineIterator(String, 'String', function (iterated) {
+ setInternalState(this, {
+ type: STRING_ITERATOR,
+ string: toString(iterated),
+ index: 0
+ });
+// `%StringIteratorPrototype%.next` method
+// https://tc39.es/ecma262/#sec-%stringiteratorprototype%.next
+}, function next() {
+ var state = getInternalState(this);
+ var string = state.string;
+ var index = state.index;
+ var point;
+ if (index >= string.length) return createIterResultObject(undefined, true);
+ point = charAt(string, index);
+ state.index += point.length;
+ return createIterResultObject(point, false);
});
-/***/ }),
-/* 243 */
-/***/ (function(module, exports, __webpack_require__) {
+/***/ }),
+/* 257 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+// TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env`
+__webpack_require__(142);
+__webpack_require__(255);
+var $ = __webpack_require__(0);
+var globalThis = __webpack_require__(3);
+var safeGetBuiltIn = __webpack_require__(239);
+var getBuiltIn = __webpack_require__(11);
+var call = __webpack_require__(4);
+var uncurryThis = __webpack_require__(2);
+var DESCRIPTORS = __webpack_require__(6);
+var USE_NATIVE_URL = __webpack_require__(141);
+var defineBuiltIn = __webpack_require__(17);
+var defineBuiltInAccessor = __webpack_require__(23);
+var defineBuiltIns = __webpack_require__(56);
+var setToStringTag = __webpack_require__(38);
+var createIteratorConstructor = __webpack_require__(160);
+var InternalStateModule = __webpack_require__(21);
+var anInstance = __webpack_require__(39);
+var isCallable = __webpack_require__(14);
+var hasOwn = __webpack_require__(13);
+var bind = __webpack_require__(43);
+var classof = __webpack_require__(47);
+var anObject = __webpack_require__(5);
+var isObject = __webpack_require__(8);
+var $toString = __webpack_require__(9);
+var create = __webpack_require__(30);
+var createPropertyDescriptor = __webpack_require__(41);
+var getIterator = __webpack_require__(83);
+var getIteratorMethod = __webpack_require__(68);
+var createIterResultObject = __webpack_require__(65);
+var validateArgumentsLength = __webpack_require__(48);
+var wellKnownSymbol = __webpack_require__(7);
+var arraySort = __webpack_require__(148);
+
+var ITERATOR = wellKnownSymbol('iterator');
+var URL_SEARCH_PARAMS = 'URLSearchParams';
+var URL_SEARCH_PARAMS_ITERATOR = URL_SEARCH_PARAMS + 'Iterator';
+var setInternalState = InternalStateModule.set;
+var getInternalParamsState = InternalStateModule.getterFor(URL_SEARCH_PARAMS);
+var getInternalIteratorState = InternalStateModule.getterFor(URL_SEARCH_PARAMS_ITERATOR);
+
+var nativeFetch = safeGetBuiltIn('fetch');
+var NativeRequest = safeGetBuiltIn('Request');
+var Headers = safeGetBuiltIn('Headers');
+var RequestPrototype = NativeRequest && NativeRequest.prototype;
+var HeadersPrototype = Headers && Headers.prototype;
+var TypeError = globalThis.TypeError;
+var encodeURIComponent = globalThis.encodeURIComponent;
+var fromCharCode = String.fromCharCode;
+var fromCodePoint = getBuiltIn('String', 'fromCodePoint');
+var $parseInt = parseInt;
+var charAt = uncurryThis(''.charAt);
+var join = uncurryThis([].join);
+var push = uncurryThis([].push);
+var replace = uncurryThis(''.replace);
+var shift = uncurryThis([].shift);
+var splice = uncurryThis([].splice);
+var split = uncurryThis(''.split);
+var stringSlice = uncurryThis(''.slice);
+var exec = uncurryThis(/./.exec);
+
+var plus = /\+/g;
+var FALLBACK_REPLACER = '\uFFFD';
+var VALID_HEX = /^[0-9a-f]+$/i;
+
+var parseHexOctet = function (string, start) {
+ var substr = stringSlice(string, start, start + 2);
+ if (!exec(VALID_HEX, substr)) return NaN;
+
+ return $parseInt(substr, 16);
+};
+
+var getLeadingOnes = function (octet) {
+ var count = 0;
+ for (var mask = 0x80; mask > 0 && (octet & mask) !== 0; mask >>= 1) {
+ count++;
+ }
+ return count;
+};
+
+var utf8Decode = function (octets) {
+ var codePoint = null;
+
+ switch (octets.length) {
+ case 1:
+ codePoint = octets[0];
+ break;
+ case 2:
+ codePoint = (octets[0] & 0x1F) << 6 | (octets[1] & 0x3F);
+ break;
+ case 3:
+ codePoint = (octets[0] & 0x0F) << 12 | (octets[1] & 0x3F) << 6 | (octets[2] & 0x3F);
+ break;
+ case 4:
+ codePoint = (octets[0] & 0x07) << 18 | (octets[1] & 0x3F) << 12 | (octets[2] & 0x3F) << 6 | (octets[3] & 0x3F);
+ break;
+ }
+
+ return codePoint > 0x10FFFF ? null : codePoint;
+};
+
+var decode = function (input) {
+ input = replace(input, plus, ' ');
+ var length = input.length;
+ var result = '';
+ var i = 0;
+
+ while (i < length) {
+ var decodedChar = charAt(input, i);
-"use strict";
+ if (decodedChar === '%') {
+ if (charAt(input, i + 1) === '%' || i + 3 > length) {
+ result += '%';
+ i++;
+ continue;
+ }
-var isObject = __webpack_require__(40);
-var createNonEnumerableProperty = __webpack_require__(59);
+ var octet = parseHexOctet(input, i + 1);
-// `InstallErrorCause` abstract operation
-// https://tc39.es/proposal-error-cause/#sec-errorobjects-install-error-cause
-module.exports = function (O, options) {
- if (isObject(options) && 'cause' in options) {
- createNonEnumerableProperty(O, 'cause', options.cause);
- }
-};
+ // eslint-disable-next-line no-self-compare -- NaN check
+ if (octet !== octet) {
+ result += decodedChar;
+ i++;
+ continue;
+ }
+ i += 2;
+ var byteSequenceLength = getLeadingOnes(octet);
-/***/ }),
-/* 244 */
-/***/ (function(module, exports, __webpack_require__) {
+ if (byteSequenceLength === 0) {
+ decodedChar = fromCharCode(octet);
+ } else {
+ if (byteSequenceLength === 1 || byteSequenceLength > 4) {
+ result += FALLBACK_REPLACER;
+ i++;
+ continue;
+ }
-"use strict";
+ var octets = [octet];
+ var sequenceIndex = 1;
-var classof = __webpack_require__(79);
+ while (sequenceIndex < byteSequenceLength) {
+ i++;
+ if (i + 3 > length || charAt(input, i) !== '%') break;
-module.exports = function (it) {
- var klass = classof(it);
- return klass === 'BigInt64Array' || klass === 'BigUint64Array';
-};
+ var nextByte = parseHexOctet(input, i + 1);
+ // eslint-disable-next-line no-self-compare -- NaN check
+ if (nextByte !== nextByte) {
+ i += 3;
+ break;
+ }
+ if (nextByte > 191 || nextByte < 128) break;
-/***/ }),
-/* 245 */
-/***/ (function(module, exports, __webpack_require__) {
+ push(octets, nextByte);
+ i += 2;
+ sequenceIndex++;
+ }
-"use strict";
+ if (octets.length !== byteSequenceLength) {
+ result += FALLBACK_REPLACER;
+ continue;
+ }
+
+ var codePoint = utf8Decode(octets);
+ if (codePoint === null) {
+ result += FALLBACK_REPLACER;
+ } else {
+ decodedChar = fromCodePoint(codePoint);
+ }
+ }
+ }
-var hasOwn = __webpack_require__(45);
+ result += decodedChar;
+ i++;
+ }
-module.exports = function (descriptor) {
- return descriptor !== undefined && (hasOwn(descriptor, 'value') || hasOwn(descriptor, 'writable'));
+ return result;
};
+var find = /[!'()~]|%20/g;
-/***/ }),
-/* 246 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
+var replacements = {
+ '!': '%21',
+ "'": '%27',
+ '(': '%28',
+ ')': '%29',
+ '~': '%7E',
+ '%20': '+'
+};
-var isObject = __webpack_require__(40);
+var replacer = function (match) {
+ return replacements[match];
+};
-module.exports = function (argument) {
- return isObject(argument) || argument === null;
+var serialize = function (it) {
+ return replace(encodeURIComponent(it), find, replacer);
};
+var URLSearchParamsIterator = createIteratorConstructor(function Iterator(params, kind) {
+ setInternalState(this, {
+ type: URL_SEARCH_PARAMS_ITERATOR,
+ target: getInternalParamsState(params).entries,
+ index: 0,
+ kind: kind
+ });
+}, URL_SEARCH_PARAMS, function next() {
+ var state = getInternalIteratorState(this);
+ var target = state.target;
+ var index = state.index++;
+ if (!target || index >= target.length) {
+ state.target = null;
+ return createIterResultObject(undefined, true);
+ }
+ var entry = target[index];
+ switch (state.kind) {
+ case 'keys': return createIterResultObject(entry.key, false);
+ case 'values': return createIterResultObject(entry.value, false);
+ } return createIterResultObject([entry.key, entry.value], false);
+}, true);
-/***/ }),
-/* 247 */
-/***/ (function(module, exports, __webpack_require__) {
+var URLSearchParamsState = function (init) {
+ this.entries = [];
+ this.url = null;
-"use strict";
+ if (init !== undefined) {
+ if (isObject(init)) this.parseObject(init);
+ else this.parseQuery(typeof init == 'string' ? charAt(init, 0) === '?' ? stringSlice(init, 1) : init : $toString(init));
+ }
+};
-var uncurryThis = __webpack_require__(34);
+URLSearchParamsState.prototype = {
+ type: URL_SEARCH_PARAMS,
+ bindURL: function (url) {
+ this.url = url;
+ this.update();
+ },
+ parseObject: function (object) {
+ var entries = this.entries;
+ var iteratorMethod = getIteratorMethod(object);
+ var iterator, next, step, entryIterator, entryNext, first, second;
-// eslint-disable-next-line es/no-map -- safe
-var MapPrototype = Map.prototype;
+ if (iteratorMethod) {
+ iterator = getIterator(object, iteratorMethod);
+ next = iterator.next;
+ while (!(step = call(next, iterator)).done) {
+ entryIterator = getIterator(anObject(step.value));
+ entryNext = entryIterator.next;
+ if (
+ (first = call(entryNext, entryIterator)).done ||
+ (second = call(entryNext, entryIterator)).done ||
+ !call(entryNext, entryIterator).done
+ ) throw new TypeError('Expected sequence with length 2');
+ push(entries, { key: $toString(first.value), value: $toString(second.value) });
+ }
+ } else for (var key in object) if (hasOwn(object, key)) {
+ push(entries, { key: key, value: $toString(object[key]) });
+ }
+ },
+ parseQuery: function (query) {
+ if (query) {
+ var entries = this.entries;
+ var attributes = split(query, '&');
+ var index = 0;
+ var attribute, entry;
+ while (index < attributes.length) {
+ attribute = attributes[index++];
+ if (attribute.length) {
+ entry = split(attribute, '=');
+ push(entries, {
+ key: decode(shift(entry)),
+ value: decode(join(entry, '='))
+ });
+ }
+ }
+ }
+ },
+ serialize: function () {
+ var entries = this.entries;
+ var result = [];
+ var index = 0;
+ var entry;
+ while (index < entries.length) {
+ entry = entries[index++];
+ push(result, serialize(entry.key) + '=' + serialize(entry.value));
+ } return join(result, '&');
+ },
+ update: function () {
+ this.entries.length = 0;
+ this.parseQuery(this.url.query);
+ },
+ updateURL: function () {
+ if (this.url) this.url.update();
+ }
+};
-module.exports = {
- // eslint-disable-next-line es/no-map -- safe
- Map: Map,
- set: uncurryThis(MapPrototype.set),
- get: uncurryThis(MapPrototype.get),
- has: uncurryThis(MapPrototype.has),
- remove: uncurryThis(MapPrototype['delete']),
- proto: MapPrototype
+// `URLSearchParams` constructor
+// https://url.spec.whatwg.org/#interface-urlsearchparams
+var URLSearchParamsConstructor = function URLSearchParams(/* init */) {
+ anInstance(this, URLSearchParamsPrototype);
+ var init = arguments.length > 0 ? arguments[0] : undefined;
+ var state = setInternalState(this, new URLSearchParamsState(init));
+ if (!DESCRIPTORS) this.size = state.entries.length;
};
+var URLSearchParamsPrototype = URLSearchParamsConstructor.prototype;
-/***/ }),
-/* 248 */
-/***/ (function(module, exports, __webpack_require__) {
+defineBuiltIns(URLSearchParamsPrototype, {
+ // `URLSearchParams.prototype.append` method
+ // https://url.spec.whatwg.org/#dom-urlsearchparams-append
+ append: function append(name, value) {
+ var state = getInternalParamsState(this);
+ validateArgumentsLength(arguments.length, 2);
+ push(state.entries, { key: $toString(name), value: $toString(value) });
+ if (!DESCRIPTORS) this.length++;
+ state.updateURL();
+ },
+ // `URLSearchParams.prototype.delete` method
+ // https://url.spec.whatwg.org/#dom-urlsearchparams-delete
+ 'delete': function (name /* , value */) {
+ var state = getInternalParamsState(this);
+ var length = validateArgumentsLength(arguments.length, 1);
+ var entries = state.entries;
+ var key = $toString(name);
+ var $value = length < 2 ? undefined : arguments[1];
+ var value = $value === undefined ? $value : $toString($value);
+ var index = 0;
+ while (index < entries.length) {
+ var entry = entries[index];
+ if (entry.key === key && (value === undefined || entry.value === value)) {
+ splice(entries, index, 1);
+ if (value !== undefined) break;
+ } else index++;
+ }
+ if (!DESCRIPTORS) this.size = entries.length;
+ state.updateURL();
+ },
+ // `URLSearchParams.prototype.get` method
+ // https://url.spec.whatwg.org/#dom-urlsearchparams-get
+ get: function get(name) {
+ var entries = getInternalParamsState(this).entries;
+ validateArgumentsLength(arguments.length, 1);
+ var key = $toString(name);
+ var index = 0;
+ for (; index < entries.length; index++) {
+ if (entries[index].key === key) return entries[index].value;
+ }
+ return null;
+ },
+ // `URLSearchParams.prototype.getAll` method
+ // https://url.spec.whatwg.org/#dom-urlsearchparams-getall
+ getAll: function getAll(name) {
+ var entries = getInternalParamsState(this).entries;
+ validateArgumentsLength(arguments.length, 1);
+ var key = $toString(name);
+ var result = [];
+ var index = 0;
+ for (; index < entries.length; index++) {
+ if (entries[index].key === key) push(result, entries[index].value);
+ }
+ return result;
+ },
+ // `URLSearchParams.prototype.has` method
+ // https://url.spec.whatwg.org/#dom-urlsearchparams-has
+ has: function has(name /* , value */) {
+ var entries = getInternalParamsState(this).entries;
+ var length = validateArgumentsLength(arguments.length, 1);
+ var key = $toString(name);
+ var $value = length < 2 ? undefined : arguments[1];
+ var value = $value === undefined ? $value : $toString($value);
+ var index = 0;
+ while (index < entries.length) {
+ var entry = entries[index++];
+ if (entry.key === key && (value === undefined || entry.value === value)) return true;
+ }
+ return false;
+ },
+ // `URLSearchParams.prototype.set` method
+ // https://url.spec.whatwg.org/#dom-urlsearchparams-set
+ set: function set(name, value) {
+ var state = getInternalParamsState(this);
+ validateArgumentsLength(arguments.length, 1);
+ var entries = state.entries;
+ var found = false;
+ var key = $toString(name);
+ var val = $toString(value);
+ var index = 0;
+ var entry;
+ for (; index < entries.length; index++) {
+ entry = entries[index];
+ if (entry.key === key) {
+ if (found) splice(entries, index--, 1);
+ else {
+ found = true;
+ entry.value = val;
+ }
+ }
+ }
+ if (!found) push(entries, { key: key, value: val });
+ if (!DESCRIPTORS) this.size = entries.length;
+ state.updateURL();
+ },
+ // `URLSearchParams.prototype.sort` method
+ // https://url.spec.whatwg.org/#dom-urlsearchparams-sort
+ sort: function sort() {
+ var state = getInternalParamsState(this);
+ arraySort(state.entries, function (a, b) {
+ return a.key > b.key ? 1 : -1;
+ });
+ state.updateURL();
+ },
+ // `URLSearchParams.prototype.forEach` method
+ forEach: function forEach(callback /* , thisArg */) {
+ var entries = getInternalParamsState(this).entries;
+ var boundFunction = bind(callback, arguments.length > 1 ? arguments[1] : undefined);
+ var index = 0;
+ var entry;
+ while (index < entries.length) {
+ entry = entries[index++];
+ boundFunction(entry.value, entry.key, this);
+ }
+ },
+ // `URLSearchParams.prototype.keys` method
+ keys: function keys() {
+ return new URLSearchParamsIterator(this, 'keys');
+ },
+ // `URLSearchParams.prototype.values` method
+ values: function values() {
+ return new URLSearchParamsIterator(this, 'values');
+ },
+ // `URLSearchParams.prototype.entries` method
+ entries: function entries() {
+ return new URLSearchParamsIterator(this, 'entries');
+ }
+}, { enumerable: true });
-"use strict";
+// `URLSearchParams.prototype[@@iterator]` method
+defineBuiltIn(URLSearchParamsPrototype, ITERATOR, URLSearchParamsPrototype.entries, { name: 'entries' });
-var sign = __webpack_require__(192);
-var roundTiesToEven = __webpack_require__(253);
+// `URLSearchParams.prototype.toString` method
+// https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior
+defineBuiltIn(URLSearchParamsPrototype, 'toString', function toString() {
+ return getInternalParamsState(this).serialize();
+}, { enumerable: true });
-var abs = Math.abs;
+// `URLSearchParams.prototype.size` getter
+// https://github.com/whatwg/url/pull/734
+if (DESCRIPTORS) defineBuiltInAccessor(URLSearchParamsPrototype, 'size', {
+ get: function size() {
+ return getInternalParamsState(this).entries.length;
+ },
+ configurable: true,
+ enumerable: true
+});
-var EPSILON = 2.220446049250313e-16; // Number.EPSILON
+setToStringTag(URLSearchParamsConstructor, URL_SEARCH_PARAMS);
-module.exports = function (x, FLOAT_EPSILON, FLOAT_MAX_VALUE, FLOAT_MIN_VALUE) {
- var n = +x;
- var absolute = abs(n);
- var s = sign(n);
- if (absolute < FLOAT_MIN_VALUE) return s * roundTiesToEven(absolute / FLOAT_MIN_VALUE / FLOAT_EPSILON) * FLOAT_MIN_VALUE * FLOAT_EPSILON;
- var a = (1 + FLOAT_EPSILON / EPSILON) * absolute;
- var result = a - (a - absolute);
- // eslint-disable-next-line no-self-compare -- NaN check
- if (result > FLOAT_MAX_VALUE || result !== result) return s * Infinity;
- return s * result;
-};
+$({ global: true, constructor: true, forced: !USE_NATIVE_URL }, {
+ URLSearchParams: URLSearchParamsConstructor
+});
+// Wrap `fetch` and `Request` for correct work with polyfilled `URLSearchParams`
+if (!USE_NATIVE_URL && isCallable(Headers)) {
+ var headersHas = uncurryThis(HeadersPrototype.has);
+ var headersSet = uncurryThis(HeadersPrototype.set);
-/***/ }),
-/* 249 */
-/***/ (function(module, exports, __webpack_require__) {
+ var wrapRequestOptions = function (init) {
+ if (isObject(init)) {
+ var body = init.body;
+ var headers;
+ if (classof(body) === URL_SEARCH_PARAMS) {
+ headers = init.headers ? new Headers(init.headers) : new Headers();
+ if (!headersHas(headers, 'content-type')) {
+ headersSet(headers, 'content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
+ }
+ return create(init, {
+ body: createPropertyDescriptor(0, $toString(body)),
+ headers: createPropertyDescriptor(0, headers)
+ });
+ }
+ } return init;
+ };
-"use strict";
+ if (isCallable(nativeFetch)) {
+ $({ global: true, enumerable: true, dontCallGetSet: true, forced: true }, {
+ fetch: function fetch(input /* , init */) {
+ return nativeFetch(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});
+ }
+ });
+ }
-var floatRound = __webpack_require__(248);
+ if (isCallable(NativeRequest)) {
+ var RequestConstructor = function Request(input /* , init */) {
+ anInstance(this, RequestPrototype);
+ return new NativeRequest(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});
+ };
-var FLOAT32_EPSILON = 1.1920928955078125e-7; // 2 ** -23;
-var FLOAT32_MAX_VALUE = 3.4028234663852886e+38; // 2 ** 128 - 2 ** 104
-var FLOAT32_MIN_VALUE = 1.1754943508222875e-38; // 2 ** -126;
+ RequestPrototype.constructor = RequestConstructor;
+ RequestConstructor.prototype = RequestPrototype;
-// `Math.fround` method implementation
-// https://tc39.es/ecma262/#sec-math.fround
-// eslint-disable-next-line es/no-math-fround -- safe
-module.exports = Math.fround || function fround(x) {
- return floatRound(x, FLOAT32_EPSILON, FLOAT32_MAX_VALUE, FLOAT32_MIN_VALUE);
+ $({ global: true, constructor: true, dontCallGetSet: true, forced: true }, {
+ Request: RequestConstructor
+ });
+ }
+}
+
+module.exports = {
+ URLSearchParams: URLSearchParamsConstructor,
+ getState: getInternalParamsState
};
/***/ }),
-/* 250 */
+/* 258 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var log = Math.log;
-var LOG10E = Math.LOG10E;
-// eslint-disable-next-line es/no-math-log10 -- safe
-module.exports = Math.log10 || function log10(x) {
- return log(x) * LOG10E;
-};
+/**
+* FUNCTION: isArray( value )
+* Validates if a value is an array.
+*
+* @param {*} value - value to be validated
+* @returns {Boolean} boolean indicating whether value is an array
+*/
+function isArray( value ) {
+ return Object.prototype.toString.call( value ) === '[object Array]';
+} // end FUNCTION isArray()
+// EXPORTS //
-/***/ }),
-/* 251 */
-/***/ (function(module, exports, __webpack_require__) {
+module.exports = Array.isArray || isArray;
-"use strict";
-var log = Math.log;
+/***/ }),
+/* 259 */
+/***/ (function(module, exports) {
-// `Math.log1p` method implementation
-// https://tc39.es/ecma262/#sec-math.log1p
-// eslint-disable-next-line es/no-math-log1p -- safe
-module.exports = Math.log1p || function log1p(x) {
- var n = +x;
- return n > -1e-8 && n < 1e-8 ? n - n * n / 2 : log(1 + n);
-};
+var g;
+
+// This works in non-strict mode
+g = (function() {
+ return this;
+})();
+
+try {
+ // This works if eval is allowed (see CSP)
+ g = g || Function("return this")() || (1,eval)("this");
+} catch(e) {
+ // This works if the window reference is available
+ if(typeof window === "object")
+ g = window;
+}
+
+// g can still be undefined, but nothing to do about it...
+// We return undefined, instead of nothing here, so it's
+// easier to handle this case. if(!global) { ...}
+
+module.exports = g;
/***/ }),
-/* 252 */
+/* 260 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var log = Math.log;
-var LN2 = Math.LN2;
-
-// `Math.log2` method
-// https://tc39.es/ecma262/#sec-math.log2
-// eslint-disable-next-line es/no-math-log2 -- safe
-module.exports = Math.log2 || function log2(x) {
- return log(x) / LN2;
-};
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+/**
+ * Iquizeles color generator
+ * @module lib/color.js;
+ */
-/***/ }),
-/* 253 */
-/***/ (function(module, exports, __webpack_require__) {
+var palettes = [[[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.0, 0.33, 0.67]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.0, 0.1, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.3, 0.2, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 0.5], [0.8, 0.9, 0.3]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 0.7, 0.4], [0.0, 0.15, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [2.0, 1.0, 0.0], [0.5, 0.2, 0.25]], [[0.8, 0.5, 0.4], [0.2, 0.4, 0.2], [2.0, 1.0, 1.0], [0.0, 0.25, 0.25]]];
-"use strict";
+var palette = palettes[0];
-var EPSILON = 2.220446049250313e-16; // Number.EPSILON
-var INVERSE_EPSILON = 1 / EPSILON;
+function channel(t, a, b, c, d, add, mul) {
+ return a + b * Math.cos(2 * Math.PI * (c * t + d)) * mul + add;
+}
-module.exports = function (n) {
- return n + INVERSE_EPSILON - INVERSE_EPSILON;
-};
+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;
/***/ }),
-/* 254 */
+/* 261 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var ceil = Math.ceil;
-var floor = Math.floor;
-// `Math.trunc` method
-// https://tc39.es/ecma262/#sec-math.trunc
-// eslint-disable-next-line es/no-math-trunc -- safe
-module.exports = Math.trunc || function trunc(x) {
- var n = +x;
- return (n > 0 ? floor : ceil)(n);
-};
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+var _tone = __webpack_require__(108);
-/***/ }),
-/* 255 */
-/***/ (function(module, exports, __webpack_require__) {
+var _tone2 = _interopRequireDefault(_tone);
-"use strict";
+var _util = __webpack_require__(143);
-var globalThis = __webpack_require__(35);
-var safeGetBuiltIn = __webpack_require__(268);
-var bind = __webpack_require__(75);
-var macrotask = __webpack_require__(167).set;
-var Queue = __webpack_require__(265);
-var IS_IOS = __webpack_require__(232);
-var IS_IOS_PEBBLE = __webpack_require__(296);
-var IS_WEBOS_WEBKIT = __webpack_require__(297);
-var IS_NODE = __webpack_require__(111);
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-var MutationObserver = globalThis.MutationObserver || globalThis.WebKitMutationObserver;
-var document = globalThis.document;
-var process = globalThis.process;
-var Promise = globalThis.Promise;
-var microtask = safeGetBuiltIn('queueMicrotask');
-var notify, toggle, node, promise, then;
+/**
+ * Kalimba
+ * @module lib/kalimba.js;
+ */
-// modern engines have queueMicrotask method
-if (!microtask) {
- var queue = new Queue();
+var player_count = 4;
- var flush = function () {
- var parent, fn;
- if (IS_NODE && (parent = process.domain)) parent.exit();
- while (fn = queue.get()) try {
- fn();
- } catch (error) {
- if (queue.head) notify();
- throw error;
+var samples = [{ root: 219.5, fn: "samples/380737__cabled-mess__sansula-01-a-raw.wav" }, { root: 260.9, fn: "samples/380736__cabled-mess__sansula-02-c-raw.wav" }, { root: 330.2, fn: "samples/380735__cabled-mess__sansula-03-e-raw.wav" }];
+
+function load(_ref) {
+ var output = _ref.output;
+
+ samples.forEach(function (sample) {
+ sample.players = [];
+ sample.index = -1;
+ for (var i = 0; i < player_count; i++) {
+ var fn = sample.fn;
+ if (window.location.href.match(/asdf.us/)) {
+ fn = "//asdf.us/kalimba/" + fn.replace("wav", "mp3");
+ }
+ var player = new _tone2.default.Player({
+ url: fn,
+ retrigger: true,
+ playbackRate: 1
+ });
+ player.name = fn;
+ var gain = new _tone2.default.Gain(1.6);
+ player.connect(gain);
+ gain.connect(output);
+ sample.players.push(player);
}
- if (parent) parent.enter();
- };
+ });
+ console.log("+ Voices:", samples.reduce(function (count, sample) {
+ return count + sample.players.length;
+ }, 0));
+}
- // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339
- // also except WebOS Webkit https://github.com/zloirock/core-js/issues/898
- if (!IS_IOS && !IS_NODE && !IS_WEBOS_WEBKIT && MutationObserver && document) {
- toggle = true;
- node = document.createTextNode('');
- new MutationObserver(flush).observe(node, { characterData: true });
- notify = function () {
- node.data = toggle = !toggle;
- };
- // environments with maybe non-completely correct, but existent Promise
- } else if (!IS_IOS_PEBBLE && Promise && Promise.resolve) {
- // Promise.resolve without an argument throws an error in LG WebOS 2
- promise = Promise.resolve(undefined);
- // workaround of WebKit ~ iOS Safari 10.1 bug
- promise.constructor = Promise;
- then = bind(promise.then, promise);
- notify = function () {
- then(flush);
- };
- // Node.js without promises
- } else if (IS_NODE) {
- notify = function () {
- process.nextTick(flush);
- };
- // for other environments - macrotask based on:
- // - setImmediate
- // - MessageChannel
- // - window.postMessage
- // - onreadystatechange
- // - setTimeout
- } else {
- // `webpack` dev server bug on IE global methods - use bind(fn, global)
- macrotask = bind(macrotask, globalThis);
- notify = function () {
- macrotask(flush);
- };
- }
+function play(interval, root) {
+ var sample = (0, _util.choice)(samples);
+ sample.index = (sample.index + 1) % sample.players.length;
- microtask = function (fn) {
- if (!queue.head) notify();
- queue.add(fn);
- };
+ var player = sample.players[sample.index];
+ player.playbackRate = interval * root / sample.root;
+ player.start();
}
-module.exports = microtask;
+function pause() {
+ // no-op
+}
+
+exports.default = { load: load, play: play, pause: pause };
+// for help tuning the kalimba samples
+// function keydown(e) {
+// // console.log(e.keyCode)
+// if (e.metaKey && last) {
+// let step = e.shiftKey ? (e.ctrlKey ? 0.01 : 0.1) : 1;
+// switch (e.keyCode) {
+// case 38: // up
+// e.preventDefault();
+// samples[0].root -= step;
+// play(last);
+// break;
+// case 40: // down
+// e.preventDefault();
+// samples[0].root += step;
+// play(last);
+// break;
+// }
+// console.log(samples[0].root);
+// }
+// }
+// window.addEventListener("keydown", keydown, true);
/***/ }),
-/* 256 */
+/* 262 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var $RangeError = RangeError;
-module.exports = function (it) {
- // eslint-disable-next-line no-self-compare -- NaN check
- if (it === it) return it;
- throw new $RangeError('NaN is not allowed');
-};
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+/**
+ * Keyboard helper
+ * @module lib/keys.js;
+ */
+var keys = {};
+var key_numbers = {};
+var letters = "zxcvbnmasdfghjklqwertyuiop";
+var numbers = "1234567890";
-/***/ }),
-/* 257 */
-/***/ (function(module, exports, __webpack_require__) {
+var callback = function callback() {};
-"use strict";
+letters.toUpperCase().split("").map(function (k, i) {
+ keys[k.charCodeAt(0)] = i;
+});
-var globalThis = __webpack_require__(35);
-var fails = __webpack_require__(33);
-var uncurryThis = __webpack_require__(34);
-var toString = __webpack_require__(41);
-var trim = __webpack_require__(124).trim;
-var whitespaces = __webpack_require__(138);
+numbers.split("").map(function (k, i) {
+ keys[k.charCodeAt(0)] = i + letters.length;
+ key_numbers[k.charCodeAt(0)] = true;
+});
-var charAt = uncurryThis(''.charAt);
-var $parseFloat = globalThis.parseFloat;
-var Symbol = globalThis.Symbol;
-var ITERATOR = Symbol && Symbol.iterator;
-var FORCED = 1 / $parseFloat(whitespaces + '-0') !== -Infinity
- // MS Edge 18- broken with boxed symbols
- || (ITERATOR && !fails(function () { $parseFloat(Object(ITERATOR)); }));
+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;
+ callback(index);
+}
-// `parseFloat` method
-// https://tc39.es/ecma262/#sec-parsefloat-string
-module.exports = FORCED ? function parseFloat(string) {
- var trimmedString = trim(toString(string));
- var result = $parseFloat(trimmedString);
- return result === 0 && charAt(trimmedString, 0) === '-' ? -0 : result;
-} : $parseFloat;
+function listen(fn) {
+ callback = fn;
+}
+exports.default = { listen: listen };
/***/ }),
-/* 258 */
+/* 263 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var globalThis = __webpack_require__(35);
-var fails = __webpack_require__(33);
-var uncurryThis = __webpack_require__(34);
-var toString = __webpack_require__(41);
-var trim = __webpack_require__(124).trim;
-var whitespaces = __webpack_require__(138);
-var $parseInt = globalThis.parseInt;
-var Symbol = globalThis.Symbol;
-var ITERATOR = Symbol && Symbol.iterator;
-var hex = /^[+-]?0x/i;
-var exec = uncurryThis(hex.exec);
-var FORCED = $parseInt(whitespaces + '08') !== 8 || $parseInt(whitespaces + '0x16') !== 22
- // MS Edge 18- broken with boxed symbols
- || (ITERATOR && !fails(function () { $parseInt(Object(ITERATOR)); }));
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
-// `parseInt` method
-// https://tc39.es/ecma262/#sec-parseint-string-radix
-module.exports = FORCED ? function parseInt(string, radix) {
- var S = trim(toString(string));
- return $parseInt(S, (radix >>> 0) || (exec(hex, S) ? 16 : 10));
-} : $parseInt;
+var _webmidi = __webpack_require__(637);
+
+function enable(play) {
+ _webmidi.WebMidi.enable().then(onEnabled).catch(function (error) {
+ return console.error(error);
+ });
+
+ // Function triggered when WEBMIDI.js is ready
+ function onEnabled() {
+ // Display available MIDI input devices
+ if (_webmidi.WebMidi.inputs.length < 1) {
+ console.log("No device detected.");
+ return;
+ } else {
+ _webmidi.WebMidi.inputs.forEach(function (device, index) {
+ document.body.innerHTML += index + ": " + device.name + "
";
+ });
+ var mySynth = _webmidi.WebMidi.inputs[0];
+ // const mySynth = WebMidi.getInputByName("TYPE NAME HERE!")
+
+ mySynth.channels[1].addListener("noteon", function (event) {
+ console.log(event.note);
+ });
+ }
+ }
+} /**
+ * MIDI
+ * @module midi.js;
+ */
+exports.default = { enable: enable };
/***/ }),
-/* 259 */
+/* 264 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var DESCRIPTORS = __webpack_require__(38);
-var uncurryThis = __webpack_require__(34);
-var call = __webpack_require__(36);
-var fails = __webpack_require__(33);
-var objectKeys = __webpack_require__(134);
-var getOwnPropertySymbolsModule = __webpack_require__(155);
-var propertyIsEnumerableModule = __webpack_require__(156);
-var toObject = __webpack_require__(47);
-var IndexedObject = __webpack_require__(115);
-// eslint-disable-next-line es/no-object-assign -- safe
-var $assign = Object.assign;
-// eslint-disable-next-line es/no-object-defineproperty -- required for testing
-var defineProperty = Object.defineProperty;
-var concat = uncurryThis([].concat);
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
-// `Object.assign` method
-// https://tc39.es/ecma262/#sec-object.assign
-module.exports = !$assign || fails(function () {
- // should have correct order of operations (Edge bug)
- if (DESCRIPTORS && $assign({ b: 1 }, $assign(defineProperty({}, 'a', {
- enumerable: true,
- get: function () {
- defineProperty(this, 'b', {
- value: 3,
- enumerable: false
- });
- }
- }), { b: 2 })).b !== 1) return true;
- // should work with symbols and should have deterministic property order (V8 bug)
- var A = {};
- var B = {};
- // eslint-disable-next-line es/no-symbol -- safe
- var symbol = Symbol('assign detection');
- var alphabet = 'abcdefghijklmnopqrst';
- A[symbol] = 7;
- // eslint-disable-next-line es/no-array-prototype-foreach -- safe
- alphabet.split('').forEach(function (chr) { B[chr] = chr; });
- return $assign({}, A)[symbol] !== 7 || objectKeys($assign({}, B)).join('') !== alphabet;
-}) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length`
- var T = toObject(target);
- var argumentsLength = arguments.length;
- var index = 1;
- var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
- var propertyIsEnumerable = propertyIsEnumerableModule.f;
- while (argumentsLength > index) {
- var S = IndexedObject(arguments[index++]);
- var keys = getOwnPropertySymbols ? concat(objectKeys(S), getOwnPropertySymbols(S)) : objectKeys(S);
- var length = keys.length;
- var j = 0;
- var key;
- while (length > j) {
- key = keys[j++];
- if (!DESCRIPTORS || call(propertyIsEnumerable, S, key)) T[key] = S[key];
- }
- } return T;
-} : $assign;
+var _tone = __webpack_require__(108);
+var _tone2 = _interopRequireDefault(_tone);
-/***/ }),
-/* 260 */
-/***/ (function(module, exports, __webpack_require__) {
+var _util = __webpack_require__(143);
-"use strict";
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Sine wave organ
+ * @module lib/organ.js;
+ */
-var uncurryThis = __webpack_require__(34);
-var hasOwn = __webpack_require__(45);
-var toIndexedObject = __webpack_require__(57);
-var indexOf = __webpack_require__(127).indexOf;
-var hiddenKeys = __webpack_require__(131);
+var root = 440;
-var push = uncurryThis([].push);
+var oscillators = {};
+var output = void 0;
+var lastPlayed = void 0;
-module.exports = function (object, names) {
- var O = toIndexedObject(object);
- var i = 0;
- var result = [];
- var key;
- for (key in O) !hasOwn(hiddenKeys, key) && hasOwn(O, key) && push(result, key);
- // Don't enum bug & hidden keys
- while (names.length > i) if (hasOwn(O, key = names[i++])) {
- ~indexOf(result, key) || push(result, key);
+function load(out) {
+ output = out;
+}
+function isPlaying(interval) {
+ var rounded = (0, _util.roundInterval)(interval);
+ var osc = oscillators[rounded];
+ return osc && osc.playing;
+}
+function play(interval) {
+ if (!output) {
+ return;
}
- return result;
-};
-
+ var rounded = (0, _util.roundInterval)(interval);
+ var osc = oscillators[rounded] = oscillators[rounded] || {};
+ if (!osc.el) {
+ osc.interval = interval;
+ osc.el = new _tone2.default.Oscillator(interval * root, "sine");
+ osc.el.connect(output);
+ }
+ osc.el.start();
+ osc.playing = true;
+ lastPlayed = osc;
+ return osc;
+}
-/***/ }),
-/* 261 */
-/***/ (function(module, exports, __webpack_require__) {
+function pause(interval) {
+ var rounded = (0, _util.roundInterval)(interval);
+ if (!oscillators[rounded]) return;
+ var osc = oscillators[rounded] = oscillators[rounded] || {};
+ if (osc.el) {
+ osc.el.stop();
+ }
+ osc.playing = false;
+ return osc;
+}
-"use strict";
+function setRoot(newRoot) {
+ root = newRoot;
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
-var DESCRIPTORS = __webpack_require__(38);
-var fails = __webpack_require__(33);
-var uncurryThis = __webpack_require__(34);
-var objectGetPrototypeOf = __webpack_require__(67);
-var objectKeys = __webpack_require__(134);
-var toIndexedObject = __webpack_require__(57);
-var $propertyIsEnumerable = __webpack_require__(156).f;
+ try {
+ for (var _iterator = Object.values(oscillators)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var osc = _step.value;
-var propertyIsEnumerable = uncurryThis($propertyIsEnumerable);
-var push = uncurryThis([].push);
+ osc.el.frequency.value = osc.interval * newRoot;
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+}
+function stop() {
+ var _iteratorNormalCompletion2 = true;
+ var _didIteratorError2 = false;
+ var _iteratorError2 = undefined;
-// in some IE versions, `propertyIsEnumerable` returns incorrect result on integer keys
-// of `null` prototype objects
-var IE_BUG = DESCRIPTORS && fails(function () {
- // eslint-disable-next-line es/no-object-create -- safe
- var O = Object.create(null);
- O[2] = 2;
- return !propertyIsEnumerable(O, 2);
-});
+ try {
+ for (var _iterator2 = Object.values(oscillators)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+ var osc = _step2.value;
-// `Object.{ entries, values }` methods implementation
-var createMethod = function (TO_ENTRIES) {
- return function (it) {
- var O = toIndexedObject(it);
- var keys = objectKeys(O);
- var IE_WORKAROUND = IE_BUG && objectGetPrototypeOf(O) === null;
- var length = keys.length;
- var i = 0;
- var result = [];
- var key;
- while (length > i) {
- key = keys[i++];
- if (!DESCRIPTORS || (IE_WORKAROUND ? key in O : propertyIsEnumerable(O, key))) {
- push(result, TO_ENTRIES ? [key, O[key]] : O[key]);
+ osc.el.stop();
+ osc.el.disconnect();
+ osc.playing = false;
+ delete osc.el;
+ }
+ } catch (err) {
+ _didIteratorError2 = true;
+ _iteratorError2 = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion2 && _iterator2.return) {
+ _iterator2.return();
+ }
+ } finally {
+ if (_didIteratorError2) {
+ throw _iteratorError2;
}
}
- return result;
- };
-};
+ }
-module.exports = {
- // `Object.entries` method
- // https://tc39.es/ecma262/#sec-object.entries
- entries: createMethod(true),
- // `Object.values` method
- // https://tc39.es/ecma262/#sec-object.values
- values: createMethod(false)
-};
+ oscillators = {};
+}
+exports.default = { load: load, isPlaying: isPlaying, play: play, pause: pause, stop: stop, setRoot: setRoot };
/***/ }),
-/* 262 */
+/* 265 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var call = __webpack_require__(36);
-var isCallable = __webpack_require__(46);
-var isObject = __webpack_require__(40);
-
-var $TypeError = TypeError;
-// `OrdinaryToPrimitive` abstract operation
-// https://tc39.es/ecma262/#sec-ordinarytoprimitive
-module.exports = function (input, pref) {
- var fn, val;
- if (pref === 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
- if (isCallable(fn = input.valueOf) && !isObject(val = call(fn, input))) return val;
- if (pref !== 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
- throw new $TypeError("Can't convert object to primitive value");
-};
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.getOutput = getOutput;
+var _tone = __webpack_require__(108);
-/***/ }),
-/* 263 */
-/***/ (function(module, exports, __webpack_require__) {
+var _tone2 = _interopRequireDefault(_tone);
-"use strict";
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-var anObject = __webpack_require__(37);
-var isObject = __webpack_require__(40);
-var newPromiseCapability = __webpack_require__(90);
+var output = null; /**
+ * Common output stage
+ * @module lib/output.js;
+ */
-module.exports = function (C, x) {
- anObject(C);
- if (isObject(x) && x.constructor === C) return x;
- var promiseCapability = newPromiseCapability.f(C);
- var resolve = promiseCapability.resolve;
- resolve(x);
- return promiseCapability.promise;
-};
+function getOutput() {
+ if (!output) output = makeOutput();
+ return output;
+}
+function makeOutput() {
+ var compressor = new _tone2.default.Compressor(-30, 3);
+ var gain = new _tone2.default.Gain(0.3);
+ compressor.connect(gain);
+ gain.toMaster();
+
+ return compressor;
+}
/***/ }),
-/* 264 */
+/* 266 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var defineProperty = __webpack_require__(51).f;
-module.exports = function (Target, Source, key) {
- key in Target || defineProperty(Target, key, {
- configurable: true,
- get: function () { return Source[key]; },
- set: function (it) { Source[key] = it; }
- });
-};
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.load = load;
+exports.dragOver = dragOver;
+exports.drop = drop;
+exports.loadSampleFromFile = loadSampleFromFile;
+var _tone = __webpack_require__(108);
-/***/ }),
-/* 265 */
-/***/ (function(module, exports, __webpack_require__) {
+var _tone2 = _interopRequireDefault(_tone);
-"use strict";
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-var Queue = function () {
- this.head = null;
- this.tail = null;
-};
+function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /**
+ * Sampler
+ * @module lib/sampler.js;
+ */
-Queue.prototype = {
- add: function (item) {
- var entry = { item: item, next: null };
- var tail = this.tail;
- if (tail) tail.next = entry;
- else this.head = entry;
- this.tail = entry;
- },
- get: function () {
- var entry = this.head;
- if (entry) {
- var next = this.head = entry.next;
- if (next === null) this.tail = null;
- return entry.item;
- }
- }
-};
+var root = 440;
-module.exports = Queue;
+var output = void 0;
+var ready = void 0;
+var current = "";
+var samples = {};
+var player_count = 12;
-/***/ }),
-/* 266 */
-/***/ (function(module, exports, __webpack_require__) {
+function load(out, readyCallback) {
+ output = out;
+ ready = readyCallback;
+ document.body.addEventListener("dragover", dragOver);
+ document.body.addEventListener("drop", drop);
+}
-"use strict";
+/**
+ * Drag and drop
+ */
+function dragOver(event) {
+ event.preventDefault();
+}
+function drop(event) {
+ event.preventDefault();
+ var files = event.dataTransfer.items ? [].concat(_toConsumableArray(event.dataTransfer.items)).filter(function (item) {
+ return item.kind === "file";
+ }).map(function (item) {
+ return item.getAsFile();
+ }) : [].concat(_toConsumableArray(event.dataTransfer.files));
-var globalThis = __webpack_require__(35);
-var fails = __webpack_require__(33);
+ var file = files[0];
+ var reader = new FileReader();
-// babel-minify and Closure Compiler transpiles RegExp('.', 'd') -> /./d and it causes SyntaxError
-var RegExp = globalThis.RegExp;
+ reader.addEventListener("load", function () {
+ return loadSampleFromFile(file, reader.result);
+ }, false);
-var FLAGS_GETTER_IS_CORRECT = !fails(function () {
- var INDICES_SUPPORT = true;
- try {
- RegExp('.', 'd');
- } catch (error) {
- INDICES_SUPPORT = false;
+ if (file) {
+ reader.readAsDataURL(file);
}
+}
- var O = {};
- // modern V8 bug
- var calls = '';
- var expected = INDICES_SUPPORT ? 'dgimsy' : 'gimsy';
+function loadSampleFromFile(file, url) {
+ var name = file.name;
- var addGetter = function (key, chr) {
- // eslint-disable-next-line es/no-object-defineproperty -- safe
- Object.defineProperty(O, key, { get: function () {
- calls += chr;
- return true;
- } });
- };
+ current = name;
- var pairs = {
- dotAll: 's',
- global: 'g',
- ignoreCase: 'i',
- multiline: 'm',
- sticky: 'y'
- };
+ var sample = samples[name] = samples[name] || {};
+ sample.root = 440;
+ sample.players = [];
+ sample.index = -1;
+ for (var i = 0; i < player_count; i++) {
+ var player = new _tone2.default.Player({
+ url: url,
+ retrigger: true,
+ playbackRate: 1
+ });
+ player.name = name;
+ player.connect(output);
+ sample.players.push(player);
+ }
+ console.log("+ Sampler:", name, "(" + sample.players.length + " voices)");
+ ready();
+}
- if (INDICES_SUPPORT) pairs.hasIndices = 'd';
+/**
+ * Player
+ */
+var last = [1, 440];
- for (var key in pairs) addGetter(key, pairs[key]);
+function stop() {
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
- // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
- var result = Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call(O);
+ try {
+ for (var _iterator = Object.values(samples)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var sample = _step.value;
- return result !== expected || calls !== expected;
-});
+ sample.players.forEach(function (player) {
+ return player.stop();
+ });
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+}
+function play(interval, root) {
+ last = [interval, root];
+ var sample = samples[current];
+ sample.index = (sample.index + 1) % sample.players.length;
+ var player = sample.players[sample.index];
+ player.playbackRate = interval * root / sample.root;
+ player.start();
+}
-module.exports = { correct: FLAGS_GETTER_IS_CORRECT };
+function pause() {
+ // no-op
+}
+
+exports.default = { load: load, play: play, pause: pause, stop: stop };
+
+// for help tuning
+function keydown(e) {
+ // console.log(e.keyCode)
+ if (e.metaKey && last && current) {
+ var sample = samples[current];
+ var step = e.shiftKey ? e.ctrlKey ? 0.1 : 1 : 10;
+ switch (e.keyCode) {
+ case 38:
+ // up
+ e.preventDefault();
+ sample.root -= step;
+ stop();
+ play(last[0], last[1]);
+ break;
+ case 40:
+ // down
+ e.preventDefault();
+ sample.root += step;
+ stop();
+ play(last[0], last[1]);
+ break;
+ }
+ }
+}
+window.addEventListener("keydown", keydown, true);
/***/ }),
/* 267 */
@@ -39361,18 +38105,73 @@ module.exports = { correct: FLAGS_GETTER_IS_CORRECT };
"use strict";
-var fails = __webpack_require__(33);
-var globalThis = __webpack_require__(35);
-
-// babel-minify and Closure Compiler transpiles RegExp('(?b)', 'g') -> /(?b)/g and it causes SyntaxError
-var $RegExp = globalThis.RegExp;
-module.exports = fails(function () {
- var re = $RegExp('(?b)', 'g');
- return re.exec('b').groups.a !== 'b' ||
- 'b'.replace(re, '$c') !== 'bc';
+Object.defineProperty(exports, "__esModule", {
+ value: true
});
+exports.scales = undefined;
+
+__webpack_require__(630);
+
+__webpack_require__(632);
+
+var _index = __webpack_require__(276);
+
+var a = void 0,
+ b = void 0; /**
+ * Scales
+ * @module client/lib/scales.js;
+ */
+var scales = exports.scales = [{ name: "natural", get: function get(i, j) {
+ return [i + 1, j + 1];
+ } }, { name: "undertone", get: function get(i, j) {
+ return [i + 1, i + j + 2];
+ } }, { name: "overtone", get: function get(i, j) {
+ return [i + j + 2, j + 1];
+ } }, {
+ name: "primes",
+ reset: function reset(x, y, w, h) {
+ a = (0, _index.Prime)().skip(x).take(w).toJS();
+ b = (0, _index.Prime)().skip(y).take(h).toJS();
+ },
+ get: function get(ii, jj, i, j) {
+ return [a[i], b[j]];
+ }
+}, {
+ name: "arithmetic",
+ reset: function reset(x, y, w, h) {
+ a = (0, _index.Arithmetic)(x + 1, x + 1).take(w).toJS();
+ b = (0, _index.Arithmetic)(y + 1, y + 1).take(h).toJS();
+ console.log(a);
+ },
+ get: function get(ii, jj, i, j) {
+ return [a[i], b[j]];
+ }
+},
+// {
+// name: "triangle",
+// reset: (x, y, w, h) => {
+// a = Triangle().skip(x).take(w).toJS();
+// b = Triangle().skip(y).take(h).toJS();
+// },
+// get: (ii, jj, i, j) => [a[i], b[j]],
+// },
+{
+ name: "collatz",
+ reset: function reset(x, y, w, h) {
+ a = (0, _index.Collatz)(x + 1).take(w).toJS();
+ b = (0, _index.Collatz)(y + 1).take(h).toJS();
+ },
+ get: function get(ii, jj, i, j) {
+ return [a[i], b[j]];
+ }
+}, {
+ name: "pythagorean",
+ get: function get(i, j) {
+ return i < j ? [Math.pow(3, i + 1), Math.pow(2, j + Math.ceil(Math.max(0, i * 1.0 / 2)))] : [Math.pow(2, i + Math.ceil(Math.max(0, j * 1.2 / 2))), Math.pow(3, j)];
+ }
+}];
/***/ }),
/* 268 */
@@ -39380,1039 +38179,1533 @@ module.exports = fails(function () {
"use strict";
-var globalThis = __webpack_require__(35);
-var DESCRIPTORS = __webpack_require__(38);
-
-// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
-var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
-// Avoid NodeJS experimental warning
-module.exports = function (name) {
- if (!DESCRIPTORS) return globalThis[name];
- var descriptor = getOwnPropertyDescriptor(globalThis, name);
- return descriptor && descriptor.value;
-};
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+/*
+ oktransition.add({
+ obj: el.style,
+ units: "px",
+ from: { left: 0 },
+ to: { left: 100 },
+ duration: 1000,
+ easing: oktransition.easing.circ_out,
+ update: function(obj){
+ console.log(obj.left)
+ }
+ finished: function(){
+ console.log("done")
+ }
+ })
+*/
+var oktransition = {};
+var transitions = [];
-/***/ }),
-/* 269 */
-/***/ (function(module, exports, __webpack_require__) {
+var last_t = 0;
+var id = 0;
-"use strict";
+var lerp = function lerp(n, a, b) {
+ return (b - a) * n + a;
+};
-// `SameValue` abstract operation
-// https://tc39.es/ecma262/#sec-samevalue
-// eslint-disable-next-line es/no-object-is -- safe
-module.exports = Object.is || function is(x, y) {
- // eslint-disable-next-line no-self-compare -- NaN check
- return x === y ? x !== 0 || 1 / x === 1 / y : x !== x && y !== y;
+oktransition.speed = 1;
+oktransition.add = function (transition) {
+ transition.id = id++;
+ transition.obj = transition.obj || {};
+ if (transition.easing) {
+ if (typeof transition.easing === "string") {
+ transition.easing = oktransition.easing[transition.easing];
+ }
+ } else {
+ transition.easing = oktransition.easing.linear;
+ }
+ if (!("from" in transition) && !("to" in transition)) {
+ transition.keys = [];
+ } else if (!("from" in transition)) {
+ transition.from = {};
+ transition.keys = Object.keys(transition.to);
+ transition.keys.forEach(function (prop) {
+ transition.from[prop] = parseFloat(transition.obj[prop]);
+ });
+ } else {
+ transition.keys = Object.keys(transition.from);
+ }
+ transition.delay = transition.delay || 0;
+ transition.start = last_t + transition.delay;
+ transition.done = false;
+ transition.after = transition.after || [];
+ transition.then = function (fn) {
+ transition.after.push(fn);
+ return transition;
+ };
+ transition.tick = 0;
+ transition.skip = transition.skip || 1;
+ transition.dt = 0;
+ transition.cancel = function () {
+ return transitions = transitions.filter(function (item) {
+ return item !== transition;
+ });
+ };
+ transitions.push(transition);
+ return transition;
+};
+oktransition.update = function (t) {
+ var done = false;
+ requestAnimationFrame(oktransition.update);
+ last_t = t * oktransition.speed;
+ if (transitions.length === 0) return;
+ transitions.forEach(function (transition, i) {
+ var dt = Math.min(1.0, (t - transition.start) / transition.duration);
+ transition.tick++;
+ if (dt < 0 || dt < 1 && transition.tick % transition.skip != 0 || transition.done) return;
+ var ddt = transition.easing(dt);
+ transition.dt = ddt;
+ transition.keys.forEach(function (prop) {
+ var val = lerp(ddt, transition.from[prop], transition.to[prop]);
+ if (transition.round) val = Math.round(val);
+ if (transition.units) val = Math.round(val) + transition.units;
+ transition.obj[prop] = val;
+ });
+ if (transition.update) {
+ transition.update(transition.obj, dt);
+ }
+ if (dt === 1) {
+ if (transition.finished) {
+ transition.finished(transition);
+ }
+ if (transition.after.length) {
+ var twn = transition.after.shift();
+ twn.obj = twn.obj || transition.obj;
+ twn.after = transition.after;
+ oktransition.add(twn);
+ }
+ if (transition.loop) {
+ transition.start = t + transition.delay;
+ } else {
+ done = true;
+ transition.done = true;
+ }
+ }
+ });
+ if (done) {
+ transitions = transitions.filter(function (transition) {
+ return !transition.done;
+ });
+ }
};
+requestAnimationFrame(oktransition.update);
-/***/ }),
-/* 270 */
-/***/ (function(module, exports, __webpack_require__) {
+oktransition.easing = {
+ linear: function linear(t) {
+ return t;
+ },
+ circ_out: function circ_out(t) {
+ return Math.sqrt(1 - (t = t - 1) * t);
+ },
+ circ_in: function circ_in(t) {
+ return -(Math.sqrt(1 - t * t) - 1);
+ },
+ circ_in_out: function circ_in_out(t) {
+ return (t *= 2) < 1 ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);
+ },
+ quad_in: function quad_in(n) {
+ return Math.pow(n, 2);
+ },
+ quad_out: function quad_out(n) {
+ return n * (n - 2) * -1;
+ },
+ quad_in_out: function quad_in_out(n) {
+ n = n * 2;
+ if (n < 1) {
+ return Math.pow(n, 2) / 2;
+ }
+ return -1 * (--n * (n - 2) - 1) / 2;
+ },
+ cubic_bezier: function cubic_bezier(mX1, mY1, mX2, mY2) {
+ function A(aA1, aA2) {
+ return 1.0 - 3.0 * aA2 + 3.0 * aA1;
+ }
+ function B(aA1, aA2) {
+ return 3.0 * aA2 - 6.0 * aA1;
+ }
+ function C(aA1) {
+ return 3.0 * aA1;
+ }
-"use strict";
+ // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
+ function CalcBezier(aT, aA1, aA2) {
+ return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;
+ }
-// Should get iterator record of a set-like object before cloning this
-// https://bugs.webkit.org/show_bug.cgi?id=289430
-module.exports = function (METHOD_NAME) {
- try {
- // eslint-disable-next-line es/no-set -- needed for test
- var baseSet = new Set();
- var setLike = {
- size: 0,
- has: function () { return true; },
- keys: function () {
- // eslint-disable-next-line es/no-object-defineproperty -- needed for test
- return Object.defineProperty({}, 'next', {
- get: function () {
- baseSet.clear();
- baseSet.add(4);
- return function () {
- return { done: true };
- };
- }
- });
+ // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
+ function GetSlope(aT, aA1, aA2) {
+ return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
+ }
+
+ function GetTForX(aX) {
+ // Newton raphson iteration
+ var aGuessT = aX;
+ for (var i = 0; i < 10; ++i) {
+ var currentSlope = GetSlope(aGuessT, mX1, mX2);
+ if (currentSlope == 0.0) return aGuessT;
+ var currentX = CalcBezier(aGuessT, mX1, mX2) - aX;
+ aGuessT -= currentX / currentSlope;
}
- };
- var result = baseSet[METHOD_NAME](setLike);
+ return aGuessT;
+ }
- return result.size !== 1 || result.values().next().value !== 4;
- } catch (error) {
- return false;
+ return function (aX) {
+ if (mX1 == mY1 && mX2 == mY2) return aX; // linear
+ return CalcBezier(aX, mY1, mY2);
+ };
}
};
+exports.default = oktransition;
/***/ }),
-/* 271 */
+/* 269 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-// https://github.com/zloirock/core-js/issues/280
-var userAgent = __webpack_require__(83);
-module.exports = /Version\/10(?:\.\d+){1,2}(?: [\w./]+)?(?: Mobile\/\w+)? Safari\//.test(userAgent);
+// MODULES //
+var isArray = __webpack_require__( 258 ),
+ isIntegerArray = __webpack_require__( 634 ),
+ isFunction = __webpack_require__( 633 );
-/***/ }),
-/* 272 */
-/***/ (function(module, exports, __webpack_require__) {
-"use strict";
+// VARIABLES //
-var $trimEnd = __webpack_require__(124).end;
-var forcedStringTrimMethod = __webpack_require__(203);
+var MAXINT = Math.pow( 2, 31 ) - 1;
-// `String.prototype.{ trimEnd, trimRight }` method
-// https://tc39.es/ecma262/#sec-string.prototype.trimend
-// https://tc39.es/ecma262/#String.prototype.trimright
-module.exports = forcedStringTrimMethod('trimEnd') ? function trimEnd() {
- return $trimEnd(this);
-// eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe
-} : ''.trimEnd;
+// FUNCTIONS //
-/***/ }),
-/* 273 */
-/***/ (function(module, exports, __webpack_require__) {
+/**
+* FUNCTION: gcd( a, b )
+* Computes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm.
+*
+* @param {Number} a - integer
+* @param {Number} b - integer
+* @returns {Number} greatest common divisor
+*/
+function gcd( a, b ) {
+ var k = 1,
+ t;
+ // Simple cases:
+ if ( a === 0 ) {
+ return b;
+ }
+ if ( b === 0 ) {
+ return a;
+ }
+ // Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...
+ while ( a%2 === 0 && b%2 === 0 ) {
+ a = a / 2; // right shift
+ b = b / 2; // right shift
+ k = k * 2; // left shift
+ }
+ // Reduce `a` to an odd number...
+ while ( a%2 === 0 ) {
+ a = a / 2; // right shift
+ }
+ // Henceforth, `a` is always odd...
+ while ( b ) {
+ // Remove all factors of 2 in `b`, as they are not common...
+ while ( b%2 === 0 ) {
+ b = b / 2; // right shift
+ }
+ // `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...
+ if ( a > b ) {
+ t = b;
+ b = a;
+ a = t;
+ }
+ b = b - a; // b=0 iff b=a
+ }
+ // Restore common factors of 2...
+ return k * a;
+} // end FUNCTION gcd()
-"use strict";
+/**
+* FUNCTION: bitwise( a, b )
+* Computes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm and bitwise operations.
+*
+* @param {Number} a - safe integer
+* @param {Number} b - safe integer
+* @returns {Number} greatest common divisor
+*/
+function bitwise( a, b ) {
+ var k = 0,
+ t;
+ // Simple cases:
+ if ( a === 0 ) {
+ return b;
+ }
+ if ( b === 0 ) {
+ return a;
+ }
+ // Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...
+ while ( (a & 1) === 0 && (b & 1) === 0 ) {
+ a >>>= 1; // right shift
+ b >>>= 1; // right shift
+ k++;
+ }
+ // Reduce `a` to an odd number...
+ while ( (a & 1) === 0 ) {
+ a >>>= 1; // right shift
+ }
+ // Henceforth, `a` is always odd...
+ while ( b ) {
+ // Remove all factors of 2 in `b`, as they are not common...
+ while ( (b & 1) === 0 ) {
+ b >>>= 1; // right shift
+ }
+ // `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...
+ if ( a > b ) {
+ t = b;
+ b = a;
+ a = t;
+ }
+ b = b - a; // b=0 iff b=a
+ }
+ // Restore common factors of 2...
+ return a << k;
+} // end FUNCTION bitwise()
-var $trimStart = __webpack_require__(124).start;
-var forcedStringTrimMethod = __webpack_require__(203);
-// `String.prototype.{ trimStart, trimLeft }` method
-// https://tc39.es/ecma262/#sec-string.prototype.trimstart
-// https://tc39.es/ecma262/#String.prototype.trimleft
-module.exports = forcedStringTrimMethod('trimStart') ? function trimStart() {
- return $trimStart(this);
-// eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe
-} : ''.trimStart;
+// GREATEST COMMON DIVISOR //
+/**
+* FUNCTION: compute( arr[, clbk] )
+* Computes the greatest common divisor.
+*
+* @param {Number[]|Number} arr - input array of integers
+* @param {Function|Number} [clbk] - accessor function for accessing array values
+* @returns {Number|Null} greatest common divisor or null
+*/
+function compute() {
+ var nargs = arguments.length,
+ args,
+ clbk,
+ arr,
+ len,
+ a, b,
+ i;
-/***/ }),
-/* 274 */
-/***/ (function(module, exports, __webpack_require__) {
+ // Copy the input arguments to an array...
+ args = new Array( nargs );
+ for ( i = 0; i < nargs; i++ ) {
+ args[ i ] = arguments[ i ];
+ }
+ // Have we been provided with integer arguments?
+ if ( isIntegerArray( args ) ) {
+ if ( nargs === 2 ) {
+ a = args[ 0 ];
+ b = args[ 1 ];
+ if ( a < 0 ) {
+ a = -a;
+ }
+ if ( b < 0 ) {
+ b = -b;
+ }
+ if ( a <= MAXINT && b <= MAXINT ) {
+ return bitwise( a, b );
+ } else {
+ return gcd( a, b );
+ }
+ }
+ arr = args;
+ }
+ // If not integers, ensure the first argument is an array...
+ else if ( !isArray( args[ 0 ] ) ) {
+ throw new TypeError( 'gcd()::invalid input argument. Must provide an array of integers. Value: `' + args[ 0 ] + '`.' );
+ }
+ // Have we been provided with more than one argument? If so, ensure that the accessor argument is a function...
+ else if ( nargs > 1 ) {
+ arr = args[ 0 ];
+ clbk = args[ 1 ];
+ if ( !isFunction( clbk ) ) {
+ throw new TypeError( 'gcd()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );
+ }
+ }
+ // We have been provided an array...
+ else {
+ arr = args[ 0 ];
+ }
+ len = arr.length;
-"use strict";
+ // Check if a sufficient number of values have been provided...
+ if ( len < 2 ) {
+ return null;
+ }
+ // If an accessor is provided, extract the array values...
+ if ( clbk ) {
+ a = new Array( len );
+ for ( i = 0; i < len; i++ ) {
+ a[ i ] = clbk( arr[ i ], i );
+ }
+ arr = a;
+ }
+ // Given an input array, ensure all array values are integers...
+ if ( nargs < 3 ) {
+ if ( !isIntegerArray( arr ) ) {
+ throw new TypeError( 'gcd()::invalid input argument. Accessed array values must be integers. Value: `' + arr + '`.' );
+ }
+ }
+ // Convert any negative integers to positive integers...
+ for ( i = 0; i < len; i++ ) {
+ a = arr[ i ];
+ if ( a < 0 ) {
+ arr[ i ] = -a;
+ }
+ }
+ // Exploit the fact that the gcd is an associative function...
+ a = arr[ 0 ];
+ for ( i = 1; i < len; i++ ) {
+ b = arr[ i ];
+ if ( b <= MAXINT && a <= MAXINT ) {
+ a = bitwise( a, b );
+ } else {
+ a = gcd( a, b );
+ }
+ }
+ return a;
+} // end FUNCTION compute()
-var call = __webpack_require__(36);
-var getBuiltIn = __webpack_require__(43);
-var wellKnownSymbol = __webpack_require__(39);
-var defineBuiltIn = __webpack_require__(49);
-module.exports = function () {
- var Symbol = getBuiltIn('Symbol');
- var SymbolPrototype = Symbol && Symbol.prototype;
- var valueOf = SymbolPrototype && SymbolPrototype.valueOf;
- var TO_PRIMITIVE = wellKnownSymbol('toPrimitive');
+// EXPORTS //
- if (SymbolPrototype && !SymbolPrototype[TO_PRIMITIVE]) {
- // `Symbol.prototype[@@toPrimitive]` method
- // https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
- // eslint-disable-next-line no-unused-vars -- required for .length
- defineBuiltIn(SymbolPrototype, TO_PRIMITIVE, function (hint) {
- return call(valueOf, this);
- }, { arity: 1 });
- }
-};
+module.exports = compute;
/***/ }),
-/* 275 */
+/* 270 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var NATIVE_SYMBOL = __webpack_require__(125);
-/* eslint-disable es/no-symbol -- safe */
-module.exports = NATIVE_SYMBOL && !!Symbol['for'] && !!Symbol.keyFor;
+var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); /**
+ * Lambdoma Triangle
+ * @module index.js;
+ */
+var _computeGcd = __webpack_require__(269);
-/***/ }),
-/* 276 */
-/***/ (function(module, exports, __webpack_require__) {
+var _computeGcd2 = _interopRequireDefault(_computeGcd);
-"use strict";
+var _keys = __webpack_require__(262);
-var toPositiveInteger = __webpack_require__(206);
+var _keys2 = _interopRequireDefault(_keys);
-var $RangeError = RangeError;
+var _color = __webpack_require__(260);
-module.exports = function (it, BYTES) {
- var offset = toPositiveInteger(it);
- if (offset % BYTES) throw new $RangeError('Wrong offset');
- return offset;
-};
+var _color2 = _interopRequireDefault(_color);
+var _kalimba = __webpack_require__(261);
-/***/ }),
-/* 277 */
-/***/ (function(module, exports, __webpack_require__) {
+var _kalimba2 = _interopRequireDefault(_kalimba);
-"use strict";
+var _sampler = __webpack_require__(266);
-var bind = __webpack_require__(75);
-var call = __webpack_require__(36);
-var aConstructor = __webpack_require__(173);
-var toObject = __webpack_require__(47);
-var lengthOfArrayLike = __webpack_require__(50);
-var getIterator = __webpack_require__(114);
-var getIteratorMethod = __webpack_require__(99);
-var isArrayIteratorMethod = __webpack_require__(187);
-var isBigIntArray = __webpack_require__(244);
-var aTypedArrayConstructor = __webpack_require__(44).aTypedArrayConstructor;
-var toBigInt = __webpack_require__(205);
+var _sampler2 = _interopRequireDefault(_sampler);
-module.exports = function from(source /* , mapfn, thisArg */) {
- var C = aConstructor(this);
- var O = toObject(source);
- var argumentsLength = arguments.length;
- var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
- var mapping = mapfn !== undefined;
- var iteratorMethod = getIteratorMethod(O);
- var i, length, result, thisIsBigIntArray, value, step, iterator, next;
- if (iteratorMethod && !isArrayIteratorMethod(iteratorMethod)) {
- iterator = getIterator(O, iteratorMethod);
- next = iterator.next;
- O = [];
- while (!(step = call(next, iterator)).done) {
- O.push(step.value);
- }
- }
- if (mapping && argumentsLength > 2) {
- mapfn = bind(mapfn, arguments[2]);
- }
- length = lengthOfArrayLike(O);
- result = new (aTypedArrayConstructor(C))(length);
- thisIsBigIntArray = isBigIntArray(result);
- for (i = 0; length > i; i++) {
- value = mapping ? mapfn(O[i], i) : O[i];
- // FF30- typed arrays doesn't properly convert objects to typed array values
- result[i] = thisIsBigIntArray ? toBigInt(value) : +value;
- }
- return result;
-};
+var _organ = __webpack_require__(264);
+var _organ2 = _interopRequireDefault(_organ);
-/***/ }),
-/* 278 */
-/***/ (function(module, exports, __webpack_require__) {
+var _midi = __webpack_require__(263);
-"use strict";
+var _midi2 = _interopRequireDefault(_midi);
-/* eslint-disable es/no-symbol -- required for testing */
-var NATIVE_SYMBOL = __webpack_require__(125);
+var _oktransition = __webpack_require__(268);
-module.exports = NATIVE_SYMBOL &&
- !Symbol.sham &&
- typeof Symbol.iterator == 'symbol';
+var _oktransition2 = _interopRequireDefault(_oktransition);
+var _output = __webpack_require__(265);
-/***/ }),
-/* 279 */
-/***/ (function(module, exports, __webpack_require__) {
+var _util = __webpack_require__(143);
-"use strict";
+var _scales = __webpack_require__(267);
-var DESCRIPTORS = __webpack_require__(38);
-var fails = __webpack_require__(33);
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-// V8 ~ Chrome 36-
-// https://bugs.chromium.org/p/v8/issues/detail?id=3334
-module.exports = DESCRIPTORS && fails(function () {
- // eslint-disable-next-line es/no-object-defineproperty -- required for testing
- return Object.defineProperty(function () { /* empty */ }, 'prototype', {
- value: 42,
- writable: false
- }).prototype !== 42;
+var instrument = _kalimba2.default;
+
+var grid = document.createElement("grid");
+var root = 440;
+var s = 50;
+var w = void 0,
+ h = void 0,
+ ws = void 0,
+ hs = void 0;
+
+var add_on = 0;
+var mul_on = 1.0;
+var add_off = 0.1;
+var mul_off = 0.9;
+
+var dragging = false;
+var erasing = false;
+var lastNote = 0;
+var notes = [];
+var base_x = 0;
+var base_y = 0;
+var scaleMode = 0;
+var is_split = false;
+var intervals = void 0;
+
+(0, _util.requestAudioContext)(function () {
+ var output = (0, _output.getOutput)();
+ document.body.appendChild(grid);
+ _kalimba2.default.load(output);
+ _organ2.default.load(output);
+ _sampler2.default.load(output, function ready() {
+ instrument = _sampler2.default;
+ });
+ build();
+ bind();
});
+function build() {
+ w = window.innerWidth;
+ h = window.innerHeight;
+ ws = Math.ceil(w / s);
+ hs = Math.ceil(h / s);
+ var scale = _scales.scales[scaleMode % _scales.scales.length];
+ if (scale.reset) {
+ scale.reset(Math.round(base_x), Math.round(base_y), ws, hs);
+ }
+ for (var i = 0; i < ws; i++) {
+ notes[i] = [];
+ for (var j = 0; j < hs; j++) {
+ notes[i][j] = add(i, j);
+ }
+ }
+ log();
+}
+function rebuild() {
+ notes.forEach(function (row) {
+ return row.forEach(function (note) {
+ return note.destroy();
+ });
+ });
+ build();
+}
+function log() {
+ var seen = {};
+ // console.log(notes);
+ for (var i = 0; i < 8; i++) {
+ for (var j = 0; j < 8; j++) {
+ var interval = notes[i][j].interval;
+ var rounded = (0, _util.roundInterval)(interval);
+ if (!seen[rounded] && (0, _util.intervalInRange)(interval, root)) {
+ seen[rounded] = notes[i][j].interval;
+ }
+ }
+ }
+ intervals = Object.values(seen).sort(function (a, b) {
+ return a - b;
+ });
+ // console.log(intervals);
+ console.log(intervals.length, "unique intervals in 8x8");
+}
+function play(note) {
+ if (!_organ2.default.isPlaying(note.interval)) {
+ var interval = note.interval;
+ // while (interval < root) {
+ // interval *= 2;
+ // }
+ // while (interval > root) {
+ // interval /= 2;
+ // }
+ var rounded = (0, _util.roundInterval)(note.interval);
+ _organ2.default.play(interval);
+ notes.forEach(function (row) {
+ return row.forEach(function (note) {
+ return note.rounded === rounded && note.div.classList.add("playing");
+ });
+ });
+ }
+}
+function trigger(note) {
+ if ((0, _util.intervalInRange)(note.interval, root)) {
+ instrument.play(note.interval, root);
+ }
+}
+function trigger_index(index) {
+ var interval = intervals[index];
+ if (interval) {
+ instrument.play(interval, root);
+ }
+}
+function pause(note) {
+ _organ2.default.pause(note.interval);
+ var rounded = (0, _util.roundInterval)(note.interval);
+ notes.forEach(function (row) {
+ return row.forEach(function (note) {
+ return note.rounded === rounded && note.div.classList.remove("playing");
+ });
+ });
+}
+function toggle(note) {
+ if (_organ2.default.isPlaying(note.rounded) || note.div.classList.contains("playing")) {
+ pause(note);
+ } else {
+ play(note);
+ }
+}
+
+function add(i, j) {
+ var ii = i + Math.round(base_x);
+ var jj = j + Math.round(base_y);
+
+ var scale = _scales.scales[scaleMode % _scales.scales.length];
+
+ var _scale$get = scale.get(ii, jj, i, j, Math.round(base_x), Math.round(base_y)),
+ _scale$get2 = _slicedToArray(_scale$get, 2),
+ a = _scale$get2[0],
+ b = _scale$get2[1];
+
+ var div = document.createElement("div");
+ var interval = a / b;
+ // const interval = root * Math.pow(2, ((b / a) % 1) + 1);
+ var add = 0;
+ var frac = void 0;
+ div.style.left = i * s + "px";
+ div.style.top = j * s + "px";
+
+ var note = {
+ interval: interval,
+ rounded: (0, _util.roundInterval)(interval, root),
+ div: div,
+ i: i,
+ j: j,
+ playing: false,
+ destroy: function destroy() {
+ div.parentNode && div.parentNode.removeChild(div);
+ },
+ recolor: function recolor(numerator, denominator) {
+ var aa = a / numerator;
+ var bb = b / denominator;
+ if (aa < bb) {
+ add = -Math.log(bb / aa) / 3.5;
+ } else {
+ add = Math.log(aa / bb) / 6;
+ }
+ var a_inv = a * denominator;
+ var b_inv = b * numerator;
+ var ba_gcd = (0, _computeGcd2.default)(a_inv, b_inv);
+ var a_disp = a_inv / ba_gcd;
+ var b_disp = b_inv / ba_gcd;
+
+ frac = Math.log2(aa / bb) % 1;
+ var frac_orig = Math.log2(a / b) % 1;
+ if (frac < 0) {
+ frac += 1;
+ }
+ if (frac_orig < 0) {
+ frac += 1;
+ }
+ if (frac_orig === 0) {
+ div.style.fontWeight = "900";
+ } else {
+ div.style.fontWeight = "500";
+ }
+
+ div.innerHTML = "
\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 connect. \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 * \n\t\t\t *
\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 * \n\t\t\t * \t
\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 connect. \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 connect. \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 * \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 *
\n\t\t *
\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 input[0]\n\t\t * and input[1]. 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 input[1] from the signal connected \n\t\t * to input[0]. If an argument is provided in the constructor, the \n\t\t * signals .value 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.
\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 input[0]. \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 input[1]. \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% input[0] and \n\t\t\t * \ta value of 1 will output 100% input[1]. \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 output[0]\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 output[1]\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 output[2]\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 min and \n\t\t * max 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: setStateAtTime(\"state\", time)\n\t\t * and getValueAtTime(time).\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 undefined\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.
\n\t\t * A single transport is created for you when the library is initialized. \n\t\t *
\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 *
\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 *
\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 input[0]\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 input[1].\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 output[0]\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 output[1]\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).
\n\t\t * \n\t\t * Mid = (Left+Right)/sqrt(2); // obtain mid-signal from left and right\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 *
\n\t\t * Side = (Left-Right)/sqrt(2); // obtain side-signal from left and righ
\n\t\t * output[0]\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 * output[1]\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.
\n\t\t * \n\t\t * Left = (Mid+Side)/sqrt(2); // obtain left signal from mid and side\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 *
\n\t\t * Right = (Mid-Side)/sqrt(2); // obtain right signal from mid and side
\n\t\t * input[0]\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 * input[1]\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 * \n\t\t * \t
\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 *
\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 *
\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:
\n\t\t * order 2: 2x^2 + 1
\n\t\t * order 3: 4x^3 + 3x
\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 *
\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 *
\n\t\t * \n\t\t * Mid *= 2*(1-width)\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 *
\n\t\t * Side *= 2*width\n\t\t * \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 *
\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 *
\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 *
\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 *
\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
note * .octaves and ramps to \n\t\t * note over the duration of .pitchDecay. \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 * \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 = 1\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.requestAudioContext = exports.intervalInRange = exports.roundInterval = exports.clamp = exports.lerp = exports.browser = 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\n/**\n * Utilities\n * @module lib/util.js;\n */\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 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 roundInterval(interval) {\n return Math.round(interval * 10000000);\n}\nvar intervalInRange = function intervalInRange(interval, root) {\n return 20 < interval * root && interval * root < 15000;\n};\nvar lerp = function lerp(n, a, b) {\n return (b - a) * n + a;\n};\nvar clamp = function clamp(n) {\n var a = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var b = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;\n return n < a ? a : n < b ? n : b;\n};\n\nfunction requestAudioContext(fn) {\n if (window.location.protocol !== \"https:\") {\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.browser = browser;\nexports.lerp = lerp;\nexports.clamp = clamp;\nexports.roundInterval = roundInterval;\nexports.intervalInRange = intervalInRange;\nexports.requestAudioContext = requestAudioContext;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/util.js\n// module id = 2\n// module chunks = 0","'use strict';\n\n/**\n* FUNCTION: isArray( value )\n*\tValidates if a value is an array.\n*\n* @param {*} value - value to be validated\n* @returns {Boolean} boolean indicating whether value is an array\n*/\nfunction isArray( value ) {\n\treturn Object.prototype.toString.call( value ) === '[object Array]';\n} // end FUNCTION isArray()\n\n// EXPORTS //\n\nmodule.exports = Array.isArray || isArray;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/validate.io-array/lib/index.js\n// module id = 3\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/**\n * Iquizeles color generator\n * @module lib/color.js;\n */\n\nvar palettes = [[[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.0, 0.33, 0.67]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.0, 0.1, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.3, 0.2, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 0.5], [0.8, 0.9, 0.3]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 0.7, 0.4], [0.0, 0.15, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [2.0, 1.0, 0.0], [0.5, 0.2, 0.25]], [[0.8, 0.5, 0.4], [0.2, 0.4, 0.2], [2.0, 1.0, 1.0], [0.0, 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 = 4\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _tone = require(\"tone\");\n\nvar _tone2 = _interopRequireDefault(_tone);\n\nvar _util = require(\"./util\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Kalimba\n * @module lib/kalimba.js;\n */\n\nvar player_count = 4;\n\nvar samples = [{ root: 219.5, fn: \"samples/380737__cabled-mess__sansula-01-a-raw.wav\" }, { root: 260.9, fn: \"samples/380736__cabled-mess__sansula-02-c-raw.wav\" }, { root: 330.2, fn: \"samples/380735__cabled-mess__sansula-03-e-raw.wav\" }];\n\nfunction load(_ref) {\n var output = _ref.output;\n\n samples.forEach(function (sample) {\n sample.players = [];\n sample.index = -1;\n for (var i = 0; i < player_count; i++) {\n var fn = sample.fn;\n if (window.location.href.match(/asdf.us/)) {\n fn = \"//asdf.us/kalimba/\" + fn.replace(\"wav\", \"mp3\");\n }\n var player = new _tone2.default.Player({\n url: fn,\n retrigger: true,\n playbackRate: 1\n });\n player.name = fn;\n var gain = new _tone2.default.Gain(1.6);\n player.connect(gain);\n gain.connect(output);\n sample.players.push(player);\n }\n });\n console.log(\"+ Voices:\", samples.reduce(function (count, sample) {\n return count + sample.players.length;\n }, 0));\n}\n\nfunction play(interval, root) {\n var sample = (0, _util.choice)(samples);\n sample.index = (sample.index + 1) % sample.players.length;\n\n var player = sample.players[sample.index];\n player.playbackRate = interval * root / sample.root;\n player.start();\n}\n\nfunction pause() {\n // no-op\n}\n\nexports.default = { load: load, play: play, pause: pause };\n\n// for help tuning the kalimba samples\n// function keydown(e) {\n// // console.log(e.keyCode)\n// if (e.metaKey && last) {\n// let step = e.shiftKey ? (e.ctrlKey ? 0.01 : 0.1) : 1;\n// switch (e.keyCode) {\n// case 38: // up\n// e.preventDefault();\n// samples[0].root -= step;\n// play(last);\n// break;\n// case 40: // down\n// e.preventDefault();\n// samples[0].root += step;\n// play(last);\n// break;\n// }\n// console.log(samples[0].root);\n// }\n// }\n// window.addEventListener(\"keydown\", keydown, true);\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/kalimba.js\n// module id = 5\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/**\n * Keyboard helper\n * @module lib/keys.js;\n */\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 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 = 6\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _webmidi = require(\"webmidi\");\n\nfunction enable(play) {\n _webmidi.WebMidi.enable().then(onEnabled).catch(function (error) {\n return console.error(error);\n });\n\n // Function triggered when WEBMIDI.js is ready\n function onEnabled() {\n // Display available MIDI input devices\n if (_webmidi.WebMidi.inputs.length < 1) {\n console.log(\"No device detected.\");\n return;\n } else {\n _webmidi.WebMidi.inputs.forEach(function (device, index) {\n document.body.innerHTML += index + \": \" + device.name + \"
\";\n });\n var mySynth = _webmidi.WebMidi.inputs[0];\n // const mySynth = WebMidi.getInputByName(\"TYPE NAME HERE!\")\n\n mySynth.channels[1].addListener(\"noteon\", function (event) {\n console.log(event.note);\n });\n }\n }\n} /**\n * MIDI\n * @module midi.js;\n */\n\nexports.default = { enable: enable };\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/midi.js\n// module id = 7\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _tone = require(\"tone\");\n\nvar _tone2 = _interopRequireDefault(_tone);\n\nvar _util = require(\"./util\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Sine wave organ\n * @module lib/organ.js;\n */\n\nvar root = 440;\n\nvar oscillators = {};\nvar output = void 0;\nvar lastPlayed = void 0;\n\nfunction load(out) {\n output = out;\n}\nfunction isPlaying(interval) {\n var rounded = (0, _util.roundInterval)(interval);\n var osc = oscillators[rounded];\n return osc && osc.playing;\n}\nfunction play(interval) {\n if (!output) {\n return;\n }\n var rounded = (0, _util.roundInterval)(interval);\n var osc = oscillators[rounded] = oscillators[rounded] || {};\n if (!osc.el) {\n osc.interval = interval;\n osc.el = new _tone2.default.Oscillator(interval * root, \"sine\");\n osc.el.connect(output);\n }\n osc.el.start();\n osc.playing = true;\n lastPlayed = osc;\n return osc;\n}\n\nfunction pause(interval) {\n var rounded = (0, _util.roundInterval)(interval);\n if (!oscillators[rounded]) return;\n var osc = oscillators[rounded] = oscillators[rounded] || {};\n if (osc.el) {\n osc.el.stop();\n }\n osc.playing = false;\n return osc;\n}\n\nfunction setRoot(newRoot) {\n root = newRoot;\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = Object.values(oscillators)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var osc = _step.value;\n\n osc.el.frequency.value = osc.interval * newRoot;\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n}\nfunction stop() {\n var _iteratorNormalCompletion2 = true;\n var _didIteratorError2 = false;\n var _iteratorError2 = undefined;\n\n try {\n for (var _iterator2 = Object.values(oscillators)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {\n var osc = _step2.value;\n\n osc.el.stop();\n osc.el.disconnect();\n osc.playing = false;\n delete osc.el;\n }\n } catch (err) {\n _didIteratorError2 = true;\n _iteratorError2 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion2 && _iterator2.return) {\n _iterator2.return();\n }\n } finally {\n if (_didIteratorError2) {\n throw _iteratorError2;\n }\n }\n }\n\n oscillators = {};\n}\n\nexports.default = { load: load, isPlaying: isPlaying, play: play, pause: pause, stop: stop, setRoot: setRoot };\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/organ.js\n// module id = 8\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.getOutput = getOutput;\n\nvar _tone = require(\"tone\");\n\nvar _tone2 = _interopRequireDefault(_tone);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar output = null; /**\n * Common output stage\n * @module lib/output.js;\n */\n\nfunction getOutput() {\n if (!output) output = makeOutput();\n return output;\n}\n\nfunction makeOutput() {\n var compressor = new _tone2.default.Compressor(-30, 3);\n var gain = new _tone2.default.Gain(0.3);\n compressor.connect(gain);\n gain.toMaster();\n\n return compressor;\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/output.js\n// module id = 9\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.load = load;\nexports.dragOver = dragOver;\nexports.drop = drop;\nexports.loadSampleFromFile = loadSampleFromFile;\n\nvar _tone = require(\"tone\");\n\nvar _tone2 = _interopRequireDefault(_tone);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /**\n * Sampler\n * @module lib/sampler.js;\n */\n\nvar root = 440;\n\nvar output = void 0;\nvar ready = void 0;\nvar current = \"\";\nvar samples = {};\n\nvar player_count = 12;\n\nfunction load(out, readyCallback) {\n output = out;\n ready = readyCallback;\n document.body.addEventListener(\"dragover\", dragOver);\n document.body.addEventListener(\"drop\", drop);\n}\n\n/**\n * Drag and drop\n */\nfunction dragOver(event) {\n event.preventDefault();\n}\nfunction drop(event) {\n event.preventDefault();\n var files = event.dataTransfer.items ? [].concat(_toConsumableArray(event.dataTransfer.items)).filter(function (item) {\n return item.kind === \"file\";\n }).map(function (item) {\n return item.getAsFile();\n }) : [].concat(_toConsumableArray(event.dataTransfer.files));\n\n var file = files[0];\n var reader = new FileReader();\n\n reader.addEventListener(\"load\", function () {\n return loadSampleFromFile(file, reader.result);\n }, false);\n\n if (file) {\n reader.readAsDataURL(file);\n }\n}\n\nfunction loadSampleFromFile(file, url) {\n var name = file.name;\n\n current = name;\n\n var sample = samples[name] = samples[name] || {};\n sample.root = 440;\n sample.players = [];\n sample.index = -1;\n for (var i = 0; i < player_count; i++) {\n var player = new _tone2.default.Player({\n url: url,\n retrigger: true,\n playbackRate: 1\n });\n player.name = name;\n player.connect(output);\n sample.players.push(player);\n }\n console.log(\"+ Sampler:\", name, \"(\" + sample.players.length + \" voices)\");\n ready();\n}\n\n/**\n * Player\n */\nvar last = [1, 440];\n\nfunction stop() {\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = Object.values(samples)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var sample = _step.value;\n\n sample.players.forEach(function (player) {\n return player.stop();\n });\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n}\nfunction play(interval, root) {\n last = [interval, root];\n var sample = samples[current];\n sample.index = (sample.index + 1) % sample.players.length;\n var player = sample.players[sample.index];\n player.playbackRate = interval * root / sample.root;\n player.start();\n}\n\nfunction pause() {\n // no-op\n}\n\nexports.default = { load: load, play: play, pause: pause, stop: stop };\n\n// for help tuning\n\nfunction keydown(e) {\n // console.log(e.keyCode)\n if (e.metaKey && last && current) {\n var sample = samples[current];\n var step = e.shiftKey ? e.ctrlKey ? 0.1 : 1 : 10;\n switch (e.keyCode) {\n case 38:\n // up\n e.preventDefault();\n sample.root -= step;\n stop();\n play(last[0], last[1]);\n break;\n case 40:\n // down\n e.preventDefault();\n sample.root += step;\n stop();\n play(last[0], last[1]);\n break;\n }\n }\n}\nwindow.addEventListener(\"keydown\", keydown, true);\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/sampler.js\n// module id = 10\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.scales = undefined;\n\nrequire(\"core-js/stable\");\n\nrequire(\"regenerator-runtime/runtime\");\n\nvar _index = require(\"../vendor/number-sequences/dist/index.js\");\n\nvar a = void 0,\n b = void 0; /**\n * Scales\n * @module client/lib/scales.js;\n */\n\nvar scales = exports.scales = [{ name: \"natural\", get: function get(i, j) {\n return [i + 1, j + 1];\n } }, { name: \"undertone\", get: function get(i, j) {\n return [i + 1, i + j + 2];\n } }, { name: \"overtone\", get: function get(i, j) {\n return [i + j + 2, j + 1];\n } }, {\n name: \"primes\",\n reset: function reset(x, y, w, h) {\n a = (0, _index.Prime)().skip(x).take(w).toJS();\n b = (0, _index.Prime)().skip(y).take(h).toJS();\n },\n get: function get(ii, jj, i, j) {\n return [a[i], b[j]];\n }\n}, {\n name: \"arithmetic\",\n reset: function reset(x, y, w, h) {\n a = (0, _index.Arithmetic)(x + 1, x + 1).take(w).toJS();\n b = (0, _index.Arithmetic)(y + 1, y + 1).take(h).toJS();\n console.log(a);\n },\n get: function get(ii, jj, i, j) {\n return [a[i], b[j]];\n }\n},\n// {\n// name: \"triangle\",\n// reset: (x, y, w, h) => {\n// a = Triangle().skip(x).take(w).toJS();\n// b = Triangle().skip(y).take(h).toJS();\n// },\n// get: (ii, jj, i, j) => [a[i], b[j]],\n// },\n{\n name: \"collatz\",\n reset: function reset(x, y, w, h) {\n a = (0, _index.Collatz)(x + 1).take(w).toJS();\n b = (0, _index.Collatz)(y + 1).take(h).toJS();\n },\n get: function get(ii, jj, i, j) {\n return [a[i], b[j]];\n }\n}, {\n name: \"pythagorean\",\n get: function get(i, j) {\n return i < j ? [Math.pow(3, i + 1), Math.pow(2, j + Math.ceil(Math.max(0, i * 1.0 / 2)))] : [Math.pow(2, i + Math.ceil(Math.max(0, j * 1.2 / 2))), Math.pow(3, j)];\n }\n}];\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/scales.js\n// module id = 11\n// module chunks = 0","'use strict';\n\n// MODULES //\n\nvar isArray = require( 'validate.io-array' ),\n\tisIntegerArray = require( 'validate.io-integer-array' ),\n\tisFunction = require( 'validate.io-function' );\n\n\n// VARIABLES //\n\nvar MAXINT = Math.pow( 2, 31 ) - 1;\n\n\n// FUNCTIONS //\n\n/**\n* FUNCTION: gcd( a, b )\n*\tComputes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm.\n*\n* @param {Number} a - integer\n* @param {Number} b - integer\n* @returns {Number} greatest common divisor\n*/\nfunction gcd( a, b ) {\n\tvar k = 1,\n\t\tt;\n\t// Simple cases:\n\tif ( a === 0 ) {\n\t\treturn b;\n\t}\n\tif ( b === 0 ) {\n\t\treturn a;\n\t}\n\t// Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...\n\twhile ( a%2 === 0 && b%2 === 0 ) {\n\t\ta = a / 2; // right shift\n\t\tb = b / 2; // right shift\n\t\tk = k * 2; // left shift\n\t}\n\t// Reduce `a` to an odd number...\n\twhile ( a%2 === 0 ) {\n\t\ta = a / 2; // right shift\n\t}\n\t// Henceforth, `a` is always odd...\n\twhile ( b ) {\n\t\t// Remove all factors of 2 in `b`, as they are not common...\n\t\twhile ( b%2 === 0 ) {\n\t\t\tb = b / 2; // right shift\n\t\t}\n\t\t// `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...\n\t\tif ( a > b ) {\n\t\t\tt = b;\n\t\t\tb = a;\n\t\t\ta = t;\n\t\t}\n\t\tb = b - a; // b=0 iff b=a\n\t}\n\t// Restore common factors of 2...\n\treturn k * a;\n} // end FUNCTION gcd()\n\n/**\n* FUNCTION: bitwise( a, b )\n*\tComputes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm and bitwise operations.\n*\n* @param {Number} a - safe integer\n* @param {Number} b - safe integer\n* @returns {Number} greatest common divisor\n*/\nfunction bitwise( a, b ) {\n\tvar k = 0,\n\t\tt;\n\t// Simple cases:\n\tif ( a === 0 ) {\n\t\treturn b;\n\t}\n\tif ( b === 0 ) {\n\t\treturn a;\n\t}\n\t// Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...\n\twhile ( (a & 1) === 0 && (b & 1) === 0 ) {\n\t\ta >>>= 1; // right shift\n\t\tb >>>= 1; // right shift\n\t\tk++;\n\t}\n\t// Reduce `a` to an odd number...\n\twhile ( (a & 1) === 0 ) {\n\t\ta >>>= 1; // right shift\n\t}\n\t// Henceforth, `a` is always odd...\n\twhile ( b ) {\n\t\t// Remove all factors of 2 in `b`, as they are not common...\n\t\twhile ( (b & 1) === 0 ) {\n\t\t\tb >>>= 1; // right shift\n\t\t}\n\t\t// `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...\n\t\tif ( a > b ) {\n\t\t\tt = b;\n\t\t\tb = a;\n\t\t\ta = t;\n\t\t}\n\t\tb = b - a; // b=0 iff b=a\n\t}\n\t// Restore common factors of 2...\n\treturn a << k;\n} // end FUNCTION bitwise()\n\n\n// GREATEST COMMON DIVISOR //\n\n/**\n* FUNCTION: compute( arr[, clbk] )\n*\tComputes the greatest common divisor.\n*\n* @param {Number[]|Number} arr - input array of integers\n* @param {Function|Number} [clbk] - accessor function for accessing array values\n* @returns {Number|Null} greatest common divisor or null\n*/\nfunction compute() {\n\tvar nargs = arguments.length,\n\t\targs,\n\t\tclbk,\n\t\tarr,\n\t\tlen,\n\t\ta, b,\n\t\ti;\n\n\t// Copy the input arguments to an array...\n\targs = new Array( nargs );\n\tfor ( i = 0; i < nargs; i++ ) {\n\t\targs[ i ] = arguments[ i ];\n\t}\n\t// Have we been provided with integer arguments?\n\tif ( isIntegerArray( args ) ) {\n\t\tif ( nargs === 2 ) {\n\t\t\ta = args[ 0 ];\n\t\t\tb = args[ 1 ];\n\t\t\tif ( a < 0 ) {\n\t\t\t\ta = -a;\n\t\t\t}\n\t\t\tif ( b < 0 ) {\n\t\t\t\tb = -b;\n\t\t\t}\n\t\t\tif ( a <= MAXINT && b <= MAXINT ) {\n\t\t\t\treturn bitwise( a, b );\n\t\t\t} else {\n\t\t\t\treturn gcd( a, b );\n\t\t\t}\n\t\t}\n\t\tarr = args;\n\t}\n\t// If not integers, ensure the first argument is an array...\n\telse if ( !isArray( args[ 0 ] ) ) {\n\t\tthrow new TypeError( 'gcd()::invalid input argument. Must provide an array of integers. Value: `' + args[ 0 ] + '`.' );\n\t}\n\t// Have we been provided with more than one argument? If so, ensure that the accessor argument is a function...\n\telse if ( nargs > 1 ) {\n\t\tarr = args[ 0 ];\n\t\tclbk = args[ 1 ];\n\t\tif ( !isFunction( clbk ) ) {\n\t\t\tthrow new TypeError( 'gcd()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );\n\t\t}\n\t}\n\t// We have been provided an array...\n\telse {\n\t\tarr = args[ 0 ];\n\t}\n\tlen = arr.length;\n\n\t// Check if a sufficient number of values have been provided...\n\tif ( len < 2 ) {\n\t\treturn null;\n\t}\n\t// If an accessor is provided, extract the array values...\n\tif ( clbk ) {\n\t\ta = new Array( len );\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\ta[ i ] = clbk( arr[ i ], i );\n\t\t}\n\t\tarr = a;\n\t}\n\t// Given an input array, ensure all array values are integers...\n\tif ( nargs < 3 ) {\n\t\tif ( !isIntegerArray( arr ) ) {\n\t\t\tthrow new TypeError( 'gcd()::invalid input argument. Accessed array values must be integers. Value: `' + arr + '`.' );\n\t\t}\n\t}\n\t// Convert any negative integers to positive integers...\n\tfor ( i = 0; i < len; i++ ) {\n\t\ta = arr[ i ];\n\t\tif ( a < 0 ) {\n\t\t\tarr[ i ] = -a;\n\t\t}\n\t}\n\t// Exploit the fact that the gcd is an associative function...\n\ta = arr[ 0 ];\n\tfor ( i = 1; i < len; i++ ) {\n\t\tb = arr[ i ];\n\t\tif ( b <= MAXINT && a <= MAXINT ) {\n\t\t\ta = bitwise( a, b );\n\t\t} else {\n\t\t\ta = gcd( a, b );\n\t\t}\n\t}\n\treturn a;\n} // end FUNCTION compute()\n\n\n// EXPORTS //\n\nmodule.exports = compute;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/compute-gcd/lib/index.js\n// module id = 12\n// module chunks = 0","\"use strict\";\n\nvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }(); /**\n * Lambdoma Triangle\n * @module index.js;\n */\n\nvar _computeGcd = require(\"compute-gcd\");\n\nvar _computeGcd2 = _interopRequireDefault(_computeGcd);\n\nvar _keys = require(\"./lib/keys\");\n\nvar _keys2 = _interopRequireDefault(_keys);\n\nvar _color = require(\"./lib/color\");\n\nvar _color2 = _interopRequireDefault(_color);\n\nvar _kalimba = require(\"./lib/kalimba\");\n\nvar _kalimba2 = _interopRequireDefault(_kalimba);\n\nvar _sampler = require(\"./lib/sampler\");\n\nvar _sampler2 = _interopRequireDefault(_sampler);\n\nvar _organ = require(\"./lib/organ\");\n\nvar _organ2 = _interopRequireDefault(_organ);\n\nvar _midi = require(\"./lib/midi\");\n\nvar _midi2 = _interopRequireDefault(_midi);\n\nvar _oktransition = require(\"./vendor/oktransition\");\n\nvar _oktransition2 = _interopRequireDefault(_oktransition);\n\nvar _output = require(\"./lib/output\");\n\nvar _util = require(\"./lib/util\");\n\nvar _scales = require(\"./lib/scales\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar instrument = _kalimba2.default;\n\nvar grid = document.createElement(\"grid\");\nvar root = 440;\nvar s = 50;\nvar w = void 0,\n h = void 0,\n ws = void 0,\n hs = void 0;\n\nvar add_on = 0;\nvar mul_on = 1.0;\nvar add_off = 0.1;\nvar mul_off = 0.9;\n\nvar dragging = false;\nvar erasing = false;\nvar lastNote = 0;\nvar notes = [];\nvar base_x = 0;\nvar base_y = 0;\nvar scaleMode = 0;\nvar is_split = false;\nvar intervals = void 0;\n\n(0, _util.requestAudioContext)(function () {\n var output = (0, _output.getOutput)();\n document.body.appendChild(grid);\n _kalimba2.default.load(output);\n _organ2.default.load(output);\n _sampler2.default.load(output, function ready() {\n instrument = _sampler2.default;\n });\n build();\n bind();\n});\n\nfunction build() {\n w = window.innerWidth;\n h = window.innerHeight;\n ws = Math.ceil(w / s);\n hs = Math.ceil(h / s);\n var scale = _scales.scales[scaleMode % _scales.scales.length];\n if (scale.reset) {\n scale.reset(Math.round(base_x), Math.round(base_y), ws, hs);\n }\n for (var i = 0; i < ws; i++) {\n notes[i] = [];\n for (var j = 0; j < hs; j++) {\n notes[i][j] = add(i, j);\n }\n }\n log();\n}\nfunction rebuild() {\n notes.forEach(function (row) {\n return row.forEach(function (note) {\n return note.destroy();\n });\n });\n build();\n}\nfunction log() {\n var seen = {};\n // console.log(notes);\n for (var i = 0; i < 8; i++) {\n for (var j = 0; j < 8; j++) {\n var interval = notes[i][j].interval;\n var rounded = (0, _util.roundInterval)(interval);\n if (!seen[rounded] && (0, _util.intervalInRange)(interval, root)) {\n seen[rounded] = notes[i][j].interval;\n }\n }\n }\n intervals = Object.values(seen).sort(function (a, b) {\n return a - b;\n });\n // console.log(intervals);\n console.log(intervals.length, \"unique intervals in 8x8\");\n}\nfunction play(note) {\n if (!_organ2.default.isPlaying(note.interval)) {\n var interval = note.interval;\n // while (interval < root) {\n // interval *= 2;\n // }\n // while (interval > root) {\n // interval /= 2;\n // }\n var rounded = (0, _util.roundInterval)(note.interval);\n _organ2.default.play(interval);\n notes.forEach(function (row) {\n return row.forEach(function (note) {\n return note.rounded === rounded && note.div.classList.add(\"playing\");\n });\n });\n }\n}\nfunction trigger(note) {\n if ((0, _util.intervalInRange)(note.interval, root)) {\n instrument.play(note.interval, root);\n }\n}\nfunction trigger_index(index) {\n var interval = intervals[index];\n if (interval) {\n instrument.play(interval, root);\n }\n}\nfunction pause(note) {\n _organ2.default.pause(note.interval);\n var rounded = (0, _util.roundInterval)(note.interval);\n notes.forEach(function (row) {\n return row.forEach(function (note) {\n return note.rounded === rounded && note.div.classList.remove(\"playing\");\n });\n });\n}\nfunction toggle(note) {\n if (_organ2.default.isPlaying(note.rounded) || note.div.classList.contains(\"playing\")) {\n pause(note);\n } else {\n play(note);\n }\n}\n\nfunction add(i, j) {\n var ii = i + Math.round(base_x);\n var jj = j + Math.round(base_y);\n\n var scale = _scales.scales[scaleMode % _scales.scales.length];\n\n var _scale$get = scale.get(ii, jj, i, j, Math.round(base_x), Math.round(base_y)),\n _scale$get2 = _slicedToArray(_scale$get, 2),\n a = _scale$get2[0],\n b = _scale$get2[1];\n\n var div = document.createElement(\"div\");\n var interval = a / b;\n // const interval = root * Math.pow(2, ((b / a) % 1) + 1);\n var add = 0;\n var frac = void 0;\n div.style.left = i * s + \"px\";\n div.style.top = j * s + \"px\";\n\n var note = {\n interval: interval,\n rounded: (0, _util.roundInterval)(interval, root),\n div: div,\n i: i,\n j: j,\n playing: false,\n destroy: function destroy() {\n div.parentNode && div.parentNode.removeChild(div);\n },\n recolor: function recolor(numerator, denominator) {\n var aa = a / numerator;\n var bb = b / denominator;\n if (aa < bb) {\n add = -Math.log(bb / aa) / 3.5;\n } else {\n add = Math.log(aa / bb) / 6;\n }\n var a_inv = a * denominator;\n var b_inv = b * numerator;\n var ba_gcd = (0, _computeGcd2.default)(a_inv, b_inv);\n var a_disp = a_inv / ba_gcd;\n var b_disp = b_inv / ba_gcd;\n\n frac = Math.log2(aa / bb) % 1;\n var frac_orig = Math.log2(a / b) % 1;\n if (frac < 0) {\n frac += 1;\n }\n if (frac_orig < 0) {\n frac += 1;\n }\n if (frac_orig === 0) {\n div.style.fontWeight = \"900\";\n } else {\n div.style.fontWeight = \"500\";\n }\n\n div.innerHTML = \"
\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 connect. \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 * \n\t\t\t *
\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 * \n\t\t\t * \t
\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 connect. \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 connect. \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 * \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 *
\n\t\t *
\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 input[0]\n\t\t * and input[1]. 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 input[1] from the signal connected \n\t\t * to input[0]. If an argument is provided in the constructor, the \n\t\t * signals .value 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.
\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 input[0]. \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 input[1]. \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% input[0] and \n\t\t\t * \ta value of 1 will output 100% input[1]. \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 output[0]\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 output[1]\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 output[2]\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 min and \n\t\t * max 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: setStateAtTime(\"state\", time)\n\t\t * and getValueAtTime(time).\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 undefined\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.
\n\t\t * A single transport is created for you when the library is initialized. \n\t\t *
\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 *
\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 *
\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 input[0]\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 input[1].\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 output[0]\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 output[1]\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).
\n\t\t * \n\t\t * Mid = (Left+Right)/sqrt(2); // obtain mid-signal from left and right\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 *
\n\t\t * Side = (Left-Right)/sqrt(2); // obtain side-signal from left and righ
\n\t\t * output[0]\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 * output[1]\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.
\n\t\t * \n\t\t * Left = (Mid+Side)/sqrt(2); // obtain left signal from mid and side\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 *
\n\t\t * Right = (Mid-Side)/sqrt(2); // obtain right signal from mid and side
\n\t\t * input[0]\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 * input[1]\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 * \n\t\t * \t
\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 *
\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 *
\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:
\n\t\t * order 2: 2x^2 + 1
\n\t\t * order 3: 4x^3 + 3x
\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 *
\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 *
\n\t\t * \n\t\t * Mid *= 2*(1-width)\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 *
\n\t\t * Side *= 2*width\n\t\t * \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 *
\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 *
\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 *
\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 *
\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
note * .octaves and ramps to \n\t\t * note over the duration of .pitchDecay. \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 * \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 = 108\n// module chunks = 0","'use strict';\nvar charAt = require('../internals/string-multibyte').charAt;\n\n// `AdvanceStringIndex` abstract operation\n// https://tc39.es/ecma262/#sec-advancestringindex\nmodule.exports = function (S, index, unicode) {\n return index + (unicode ? charAt(S, index).length : 1);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/advance-string-index.js\n// module id = 109\n// module chunks = 0","'use strict';\n// eslint-disable-next-line es/no-typed-arrays -- safe\nmodule.exports = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-buffer-basic-detection.js\n// module id = 110\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar DESCRIPTORS = require('../internals/descriptors');\nvar NATIVE_ARRAY_BUFFER = require('../internals/array-buffer-basic-detection');\nvar FunctionName = require('../internals/function-name');\nvar createNonEnumerableProperty = require('../internals/create-non-enumerable-property');\nvar defineBuiltInAccessor = require('../internals/define-built-in-accessor');\nvar defineBuiltIns = require('../internals/define-built-ins');\nvar fails = require('../internals/fails');\nvar anInstance = require('../internals/an-instance');\nvar toIntegerOrInfinity = require('../internals/to-integer-or-infinity');\nvar toLength = require('../internals/to-length');\nvar toIndex = require('../internals/to-index');\nvar fround = require('../internals/math-fround');\nvar IEEE754 = require('../internals/ieee754');\nvar getPrototypeOf = require('../internals/object-get-prototype-of');\nvar setPrototypeOf = require('../internals/object-set-prototype-of');\nvar arrayFill = require('../internals/array-fill');\nvar arraySlice = require('../internals/array-slice');\nvar inheritIfRequired = require('../internals/inherit-if-required');\nvar copyConstructorProperties = require('../internals/copy-constructor-properties');\nvar setToStringTag = require('../internals/set-to-string-tag');\nvar InternalStateModule = require('../internals/internal-state');\n\nvar PROPER_FUNCTION_NAME = FunctionName.PROPER;\nvar CONFIGURABLE_FUNCTION_NAME = FunctionName.CONFIGURABLE;\nvar ARRAY_BUFFER = 'ArrayBuffer';\nvar DATA_VIEW = 'DataView';\nvar PROTOTYPE = 'prototype';\nvar WRONG_LENGTH = 'Wrong length';\nvar WRONG_INDEX = 'Wrong index';\nvar getInternalArrayBufferState = InternalStateModule.getterFor(ARRAY_BUFFER);\nvar getInternalDataViewState = InternalStateModule.getterFor(DATA_VIEW);\nvar setInternalState = InternalStateModule.set;\nvar NativeArrayBuffer = globalThis[ARRAY_BUFFER];\nvar $ArrayBuffer = NativeArrayBuffer;\nvar ArrayBufferPrototype = $ArrayBuffer && $ArrayBuffer[PROTOTYPE];\nvar $DataView = globalThis[DATA_VIEW];\nvar DataViewPrototype = $DataView && $DataView[PROTOTYPE];\nvar ObjectPrototype = Object.prototype;\nvar Array = globalThis.Array;\nvar RangeError = globalThis.RangeError;\nvar fill = uncurryThis(arrayFill);\nvar reverse = uncurryThis([].reverse);\n\nvar packIEEE754 = IEEE754.pack;\nvar unpackIEEE754 = IEEE754.unpack;\n\nvar packInt8 = function (number) {\n return [number & 0xFF];\n};\n\nvar packInt16 = function (number) {\n return [number & 0xFF, number >> 8 & 0xFF];\n};\n\nvar packInt32 = function (number) {\n return [number & 0xFF, number >> 8 & 0xFF, number >> 16 & 0xFF, number >> 24 & 0xFF];\n};\n\nvar unpackInt32 = function (buffer) {\n return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];\n};\n\nvar packFloat32 = function (number) {\n return packIEEE754(fround(number), 23, 4);\n};\n\nvar packFloat64 = function (number) {\n return packIEEE754(number, 52, 8);\n};\n\nvar addGetter = function (Constructor, key, getInternalState) {\n defineBuiltInAccessor(Constructor[PROTOTYPE], key, {\n configurable: true,\n get: function () {\n return getInternalState(this)[key];\n }\n });\n};\n\nvar get = function (view, count, index, isLittleEndian) {\n var store = getInternalDataViewState(view);\n var intIndex = toIndex(index);\n var boolIsLittleEndian = !!isLittleEndian;\n if (intIndex + count > store.byteLength) throw new RangeError(WRONG_INDEX);\n var bytes = store.bytes;\n var start = intIndex + store.byteOffset;\n var pack = arraySlice(bytes, start, start + count);\n return boolIsLittleEndian ? pack : reverse(pack);\n};\n\nvar set = function (view, count, index, conversion, value, isLittleEndian) {\n var store = getInternalDataViewState(view);\n var intIndex = toIndex(index);\n var pack = conversion(+value);\n var boolIsLittleEndian = !!isLittleEndian;\n if (intIndex + count > store.byteLength) throw new RangeError(WRONG_INDEX);\n var bytes = store.bytes;\n var start = intIndex + store.byteOffset;\n for (var i = 0; i < count; i++) bytes[start + i] = pack[boolIsLittleEndian ? i : count - i - 1];\n};\n\nif (!NATIVE_ARRAY_BUFFER) {\n $ArrayBuffer = function ArrayBuffer(length) {\n anInstance(this, ArrayBufferPrototype);\n var byteLength = toIndex(length);\n setInternalState(this, {\n type: ARRAY_BUFFER,\n bytes: fill(Array(byteLength), 0),\n byteLength: byteLength\n });\n if (!DESCRIPTORS) {\n this.byteLength = byteLength;\n this.detached = false;\n }\n };\n\n ArrayBufferPrototype = $ArrayBuffer[PROTOTYPE];\n\n $DataView = function DataView(buffer, byteOffset, byteLength) {\n anInstance(this, DataViewPrototype);\n anInstance(buffer, ArrayBufferPrototype);\n var bufferState = getInternalArrayBufferState(buffer);\n var bufferLength = bufferState.byteLength;\n var offset = toIntegerOrInfinity(byteOffset);\n if (offset < 0 || offset > bufferLength) throw new RangeError('Wrong offset');\n byteLength = byteLength === undefined ? bufferLength - offset : toLength(byteLength);\n if (offset + byteLength > bufferLength) throw new RangeError(WRONG_LENGTH);\n setInternalState(this, {\n type: DATA_VIEW,\n buffer: buffer,\n byteLength: byteLength,\n byteOffset: offset,\n bytes: bufferState.bytes\n });\n if (!DESCRIPTORS) {\n this.buffer = buffer;\n this.byteLength = byteLength;\n this.byteOffset = offset;\n }\n };\n\n DataViewPrototype = $DataView[PROTOTYPE];\n\n if (DESCRIPTORS) {\n addGetter($ArrayBuffer, 'byteLength', getInternalArrayBufferState);\n addGetter($DataView, 'buffer', getInternalDataViewState);\n addGetter($DataView, 'byteLength', getInternalDataViewState);\n addGetter($DataView, 'byteOffset', getInternalDataViewState);\n }\n\n defineBuiltIns(DataViewPrototype, {\n getInt8: function getInt8(byteOffset) {\n return get(this, 1, byteOffset)[0] << 24 >> 24;\n },\n getUint8: function getUint8(byteOffset) {\n return get(this, 1, byteOffset)[0];\n },\n getInt16: function getInt16(byteOffset /* , littleEndian */) {\n var bytes = get(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : false);\n return (bytes[1] << 8 | bytes[0]) << 16 >> 16;\n },\n getUint16: function getUint16(byteOffset /* , littleEndian */) {\n var bytes = get(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : false);\n return bytes[1] << 8 | bytes[0];\n },\n getInt32: function getInt32(byteOffset /* , littleEndian */) {\n return unpackInt32(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false));\n },\n getUint32: function getUint32(byteOffset /* , littleEndian */) {\n return unpackInt32(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false)) >>> 0;\n },\n getFloat32: function getFloat32(byteOffset /* , littleEndian */) {\n return unpackIEEE754(get(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : false), 23);\n },\n getFloat64: function getFloat64(byteOffset /* , littleEndian */) {\n return unpackIEEE754(get(this, 8, byteOffset, arguments.length > 1 ? arguments[1] : false), 52);\n },\n setInt8: function setInt8(byteOffset, value) {\n set(this, 1, byteOffset, packInt8, value);\n },\n setUint8: function setUint8(byteOffset, value) {\n set(this, 1, byteOffset, packInt8, value);\n },\n setInt16: function setInt16(byteOffset, value /* , littleEndian */) {\n set(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : false);\n },\n setUint16: function setUint16(byteOffset, value /* , littleEndian */) {\n set(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : false);\n },\n setInt32: function setInt32(byteOffset, value /* , littleEndian */) {\n set(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : false);\n },\n setUint32: function setUint32(byteOffset, value /* , littleEndian */) {\n set(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : false);\n },\n setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) {\n set(this, 4, byteOffset, packFloat32, value, arguments.length > 2 ? arguments[2] : false);\n },\n setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) {\n set(this, 8, byteOffset, packFloat64, value, arguments.length > 2 ? arguments[2] : false);\n }\n });\n} else {\n var INCORRECT_ARRAY_BUFFER_NAME = PROPER_FUNCTION_NAME && NativeArrayBuffer.name !== ARRAY_BUFFER;\n /* eslint-disable no-new, sonarjs/inconsistent-function-call -- required for testing */\n if (!fails(function () {\n NativeArrayBuffer(1);\n }) || !fails(function () {\n new NativeArrayBuffer(-1);\n }) || fails(function () {\n new NativeArrayBuffer();\n new NativeArrayBuffer(1.5);\n new NativeArrayBuffer(NaN);\n return NativeArrayBuffer.length !== 1 || INCORRECT_ARRAY_BUFFER_NAME && !CONFIGURABLE_FUNCTION_NAME;\n })) {\n /* eslint-enable no-new, sonarjs/inconsistent-function-call -- required for testing */\n $ArrayBuffer = function ArrayBuffer(length) {\n anInstance(this, ArrayBufferPrototype);\n return inheritIfRequired(new NativeArrayBuffer(toIndex(length)), this, $ArrayBuffer);\n };\n\n $ArrayBuffer[PROTOTYPE] = ArrayBufferPrototype;\n\n ArrayBufferPrototype.constructor = $ArrayBuffer;\n\n copyConstructorProperties($ArrayBuffer, NativeArrayBuffer);\n } else if (INCORRECT_ARRAY_BUFFER_NAME && CONFIGURABLE_FUNCTION_NAME) {\n createNonEnumerableProperty(NativeArrayBuffer, 'name', ARRAY_BUFFER);\n }\n\n // WebKit bug - the same parent prototype for typed arrays and data view\n if (setPrototypeOf && getPrototypeOf(DataViewPrototype) !== ObjectPrototype) {\n setPrototypeOf(DataViewPrototype, ObjectPrototype);\n }\n\n // iOS Safari 7.x bug\n var testView = new $DataView(new $ArrayBuffer(2));\n var $setInt8 = uncurryThis(DataViewPrototype.setInt8);\n testView.setInt8(0, 2147483648);\n testView.setInt8(1, 2147483649);\n if (testView.getInt8(0) || !testView.getInt8(1)) defineBuiltIns(DataViewPrototype, {\n setInt8: function setInt8(byteOffset, value) {\n $setInt8(this, byteOffset, value << 24 >> 24);\n },\n setUint8: function setUint8(byteOffset, value) {\n $setInt8(this, byteOffset, value << 24 >> 24);\n }\n }, { unsafe: true });\n}\n\nsetToStringTag($ArrayBuffer, ARRAY_BUFFER);\nsetToStringTag($DataView, DATA_VIEW);\n\nmodule.exports = {\n ArrayBuffer: $ArrayBuffer,\n DataView: $DataView\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-buffer.js\n// module id = 111\n// module chunks = 0","'use strict';\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\n\nmodule.exports = function (Constructor, list, $length) {\n var index = 0;\n var length = arguments.length > 2 ? $length : lengthOfArrayLike(list);\n var result = new Constructor(length);\n while (length > index) result[index] = list[index++];\n return result;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-from-constructor-and-list.js\n// module id = 112\n// module chunks = 0","'use strict';\nvar bind = require('../internals/function-bind-context');\nvar IndexedObject = require('../internals/indexed-object');\nvar toObject = require('../internals/to-object');\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\n\n// `Array.prototype.{ findLast, findLastIndex }` methods implementation\nvar createMethod = function (TYPE) {\n var IS_FIND_LAST_INDEX = TYPE === 1;\n return function ($this, callbackfn, that) {\n var O = toObject($this);\n var self = IndexedObject(O);\n var index = lengthOfArrayLike(self);\n var boundFunction = bind(callbackfn, that);\n var value, result;\n while (index-- > 0) {\n value = self[index];\n result = boundFunction(value, index, O);\n if (result) switch (TYPE) {\n case 0: return value; // findLast\n case 1: return index; // findLastIndex\n }\n }\n return IS_FIND_LAST_INDEX ? -1 : undefined;\n };\n};\n\nmodule.exports = {\n // `Array.prototype.findLast` method\n // https://github.com/tc39/proposal-array-find-from-last\n findLast: createMethod(0),\n // `Array.prototype.findLastIndex` method\n // https://github.com/tc39/proposal-array-find-from-last\n findLastIndex: createMethod(1)\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-iteration-from-last.js\n// module id = 113\n// module chunks = 0","'use strict';\nvar aCallable = require('../internals/a-callable');\nvar toObject = require('../internals/to-object');\nvar IndexedObject = require('../internals/indexed-object');\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\n\nvar $TypeError = TypeError;\n\nvar REDUCE_EMPTY = 'Reduce of empty array with no initial value';\n\n// `Array.prototype.{ reduce, reduceRight }` methods implementation\nvar createMethod = function (IS_RIGHT) {\n return function (that, callbackfn, argumentsLength, memo) {\n var O = toObject(that);\n var self = IndexedObject(O);\n var length = lengthOfArrayLike(O);\n aCallable(callbackfn);\n if (length === 0 && argumentsLength < 2) throw new $TypeError(REDUCE_EMPTY);\n var index = IS_RIGHT ? length - 1 : 0;\n var i = IS_RIGHT ? -1 : 1;\n if (argumentsLength < 2) while (true) {\n if (index in self) {\n memo = self[index];\n index += i;\n break;\n }\n index += i;\n if (IS_RIGHT ? index < 0 : length <= index) {\n throw new $TypeError(REDUCE_EMPTY);\n }\n }\n for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {\n memo = callbackfn(memo, self[index], index, O);\n }\n return memo;\n };\n};\n\nmodule.exports = {\n // `Array.prototype.reduce` method\n // https://tc39.es/ecma262/#sec-array.prototype.reduce\n left: createMethod(false),\n // `Array.prototype.reduceRight` method\n // https://tc39.es/ecma262/#sec-array.prototype.reduceright\n right: createMethod(true)\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-reduce.js\n// module id = 114\n// module chunks = 0","'use strict';\nvar wellKnownSymbol = require('../internals/well-known-symbol');\n\nvar ITERATOR = wellKnownSymbol('iterator');\nvar SAFE_CLOSING = false;\n\ntry {\n var called = 0;\n var iteratorWithReturn = {\n next: function () {\n return { done: !!called++ };\n },\n 'return': function () {\n SAFE_CLOSING = true;\n }\n };\n iteratorWithReturn[ITERATOR] = function () {\n return this;\n };\n // eslint-disable-next-line es/no-array-from, no-throw-literal -- required for testing\n Array.from(iteratorWithReturn, function () { throw 2; });\n} catch (error) { /* empty */ }\n\nmodule.exports = function (exec, SKIP_CLOSING) {\n try {\n if (!SKIP_CLOSING && !SAFE_CLOSING) return false;\n } catch (error) { return false; } // workaround of old WebKit + `eval` bug\n var ITERATION_SUPPORT = false;\n try {\n var object = {};\n object[ITERATOR] = function () {\n return {\n next: function () {\n return { done: ITERATION_SUPPORT = true };\n }\n };\n };\n exec(object);\n } catch (error) { /* empty */ }\n return ITERATION_SUPPORT;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/check-correctness-of-iteration.js\n// module id = 115\n// module chunks = 0","'use strict';\nvar $ = require('../internals/export');\nvar globalThis = require('../internals/global-this');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar isForced = require('../internals/is-forced');\nvar defineBuiltIn = require('../internals/define-built-in');\nvar InternalMetadataModule = require('../internals/internal-metadata');\nvar iterate = require('../internals/iterate');\nvar anInstance = require('../internals/an-instance');\nvar isCallable = require('../internals/is-callable');\nvar isNullOrUndefined = require('../internals/is-null-or-undefined');\nvar isObject = require('../internals/is-object');\nvar fails = require('../internals/fails');\nvar checkCorrectnessOfIteration = require('../internals/check-correctness-of-iteration');\nvar setToStringTag = require('../internals/set-to-string-tag');\nvar inheritIfRequired = require('../internals/inherit-if-required');\n\nmodule.exports = function (CONSTRUCTOR_NAME, wrapper, common) {\n var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;\n var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;\n var ADDER = IS_MAP ? 'set' : 'add';\n var NativeConstructor = globalThis[CONSTRUCTOR_NAME];\n var NativePrototype = NativeConstructor && NativeConstructor.prototype;\n var Constructor = NativeConstructor;\n var exported = {};\n\n var fixMethod = function (KEY) {\n var uncurriedNativeMethod = uncurryThis(NativePrototype[KEY]);\n defineBuiltIn(NativePrototype, KEY,\n KEY === 'add' ? function add(value) {\n uncurriedNativeMethod(this, value === 0 ? 0 : value);\n return this;\n } : KEY === 'delete' ? function (key) {\n return IS_WEAK && !isObject(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);\n } : KEY === 'get' ? function get(key) {\n return IS_WEAK && !isObject(key) ? undefined : uncurriedNativeMethod(this, key === 0 ? 0 : key);\n } : KEY === 'has' ? function has(key) {\n return IS_WEAK && !isObject(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);\n } : function set(key, value) {\n uncurriedNativeMethod(this, key === 0 ? 0 : key, value);\n return this;\n }\n );\n };\n\n var REPLACE = isForced(\n CONSTRUCTOR_NAME,\n !isCallable(NativeConstructor) || !(IS_WEAK || NativePrototype.forEach && !fails(function () {\n new NativeConstructor().entries().next();\n }))\n );\n\n if (REPLACE) {\n // create collection constructor\n Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER);\n InternalMetadataModule.enable();\n } else if (isForced(CONSTRUCTOR_NAME, true)) {\n var instance = new Constructor();\n // early implementations not supports chaining\n var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) !== instance;\n // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false\n var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });\n // most early implementations doesn't supports iterables, most modern - not close it correctly\n // eslint-disable-next-line no-new -- required for testing\n var ACCEPT_ITERABLES = checkCorrectnessOfIteration(function (iterable) { new NativeConstructor(iterable); });\n // for early implementations -0 and +0 not the same\n var BUGGY_ZERO = !IS_WEAK && fails(function () {\n // V8 ~ Chromium 42- fails only with 5+ elements\n var $instance = new NativeConstructor();\n var index = 5;\n while (index--) $instance[ADDER](index, index);\n return !$instance.has(-0);\n });\n\n if (!ACCEPT_ITERABLES) {\n Constructor = wrapper(function (dummy, iterable) {\n anInstance(dummy, NativePrototype);\n var that = inheritIfRequired(new NativeConstructor(), dummy, Constructor);\n if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });\n return that;\n });\n Constructor.prototype = NativePrototype;\n NativePrototype.constructor = Constructor;\n }\n\n if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {\n fixMethod('delete');\n fixMethod('has');\n IS_MAP && fixMethod('get');\n }\n\n if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);\n\n // weak collections should not contains .clear method\n if (IS_WEAK && NativePrototype.clear) delete NativePrototype.clear;\n }\n\n exported[CONSTRUCTOR_NAME] = Constructor;\n $({ global: true, constructor: true, forced: Constructor !== NativeConstructor }, exported);\n\n setToStringTag(Constructor, CONSTRUCTOR_NAME);\n\n if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP);\n\n return Constructor;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/collection.js\n// module id = 116\n// module chunks = 0","'use strict';\nvar tryToString = require('../internals/try-to-string');\n\nvar $TypeError = TypeError;\n\nmodule.exports = function (O, P) {\n if (!delete O[P]) throw new $TypeError('Cannot delete property ' + tryToString(P) + ' of ' + tryToString(O));\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/delete-property-or-throw.js\n// module id = 117\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar isObject = require('../internals/is-object');\n\nvar document = globalThis.document;\n// typeof document.createElement is 'object' in old IE\nvar EXISTS = isObject(document) && isObject(document.createElement);\n\nmodule.exports = function (it) {\n return EXISTS ? document.createElement(it) : {};\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/document-create-element.js\n// module id = 118\n// module chunks = 0","'use strict';\n/* global Bun, Deno -- detection */\nvar globalThis = require('../internals/global-this');\nvar userAgent = require('../internals/environment-user-agent');\nvar classof = require('../internals/classof-raw');\n\nvar userAgentStartsWith = function (string) {\n return userAgent.slice(0, string.length) === string;\n};\n\nmodule.exports = (function () {\n if (userAgentStartsWith('Bun/')) return 'BUN';\n if (userAgentStartsWith('Cloudflare-Workers')) return 'CLOUDFLARE';\n if (userAgentStartsWith('Deno/')) return 'DENO';\n if (userAgentStartsWith('Node.js/')) return 'NODE';\n if (globalThis.Bun && typeof Bun.version == 'string') return 'BUN';\n if (globalThis.Deno && typeof Deno.version == 'object') return 'DENO';\n if (classof(globalThis.process) === 'process') return 'NODE';\n if (globalThis.window && globalThis.document) return 'BROWSER';\n return 'REST';\n})();\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/environment.js\n// module id = 119\n// module chunks = 0","'use strict';\n// TODO: Remove from `core-js@4` since it's moved to entry points\nrequire('../modules/es.regexp.exec');\nvar call = require('../internals/function-call');\nvar defineBuiltIn = require('../internals/define-built-in');\nvar regexpExec = require('../internals/regexp-exec');\nvar fails = require('../internals/fails');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\nvar createNonEnumerableProperty = require('../internals/create-non-enumerable-property');\n\nvar SPECIES = wellKnownSymbol('species');\nvar RegExpPrototype = RegExp.prototype;\n\nmodule.exports = function (KEY, exec, FORCED, SHAM) {\n var SYMBOL = wellKnownSymbol(KEY);\n\n var DELEGATES_TO_SYMBOL = !fails(function () {\n // String methods call symbol-named RegExp methods\n var O = {};\n O[SYMBOL] = function () { return 7; };\n return ''[KEY](O) !== 7;\n });\n\n var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails(function () {\n // Symbol-named RegExp methods call .exec\n var execCalled = false;\n var re = /a/;\n\n if (KEY === 'split') {\n // We can't use real regex here since it causes deoptimization\n // and serious performance degradation in V8\n // https://github.com/zloirock/core-js/issues/306\n re = {};\n // RegExp[@@split] doesn't call the regex's exec method, but first creates\n // a new one. We need to return the patched regex when creating the new one.\n re.constructor = {};\n re.constructor[SPECIES] = function () { return re; };\n re.flags = '';\n re[SYMBOL] = /./[SYMBOL];\n }\n\n re.exec = function () {\n execCalled = true;\n return null;\n };\n\n re[SYMBOL]('');\n return !execCalled;\n });\n\n if (\n !DELEGATES_TO_SYMBOL ||\n !DELEGATES_TO_EXEC ||\n FORCED\n ) {\n var nativeRegExpMethod = /./[SYMBOL];\n var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) {\n var $exec = regexp.exec;\n if ($exec === regexpExec || $exec === RegExpPrototype.exec) {\n if (DELEGATES_TO_SYMBOL && !forceStringMethod) {\n // The native String method already delegates to @@method (this\n // polyfilled function), leasing to infinite recursion.\n // We avoid it by directly calling the native @@method method.\n return { done: true, value: call(nativeRegExpMethod, regexp, str, arg2) };\n }\n return { done: true, value: call(nativeMethod, str, regexp, arg2) };\n }\n return { done: false };\n });\n\n defineBuiltIn(String.prototype, KEY, methods[0]);\n defineBuiltIn(RegExpPrototype, SYMBOL, methods[1]);\n }\n\n if (SHAM) createNonEnumerableProperty(RegExpPrototype[SYMBOL], 'sham', true);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/fix-regexp-well-known-symbol-logic.js\n// module id = 120\n// module chunks = 0","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar aCallable = require('../internals/a-callable');\n\nmodule.exports = function (object, key, method) {\n try {\n // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe\n return uncurryThis(aCallable(Object.getOwnPropertyDescriptor(object, key)[method]));\n } catch (error) { /* empty */ }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/function-uncurry-this-accessor.js\n// module id = 121\n// module chunks = 0","'use strict';\nvar isObject = require('../internals/is-object');\nvar classof = require('../internals/classof-raw');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\n\nvar MATCH = wellKnownSymbol('match');\n\n// `IsRegExp` abstract operation\n// https://tc39.es/ecma262/#sec-isregexp\nmodule.exports = function (it) {\n var isRegExp;\n return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : classof(it) === 'RegExp');\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/is-regexp.js\n// module id = 122\n// module chunks = 0","'use strict';\n// Should throw an error on invalid iterator\n// https://issues.chromium.org/issues/336839115\nmodule.exports = function (methodName, argument) {\n // eslint-disable-next-line es/no-iterator -- required for testing\n var method = typeof Iterator == 'function' && Iterator.prototype[methodName];\n if (method) try {\n method.call({ next: null }, argument).next();\n } catch (error) {\n return true;\n }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/iterator-helper-throws-on-invalid-iterator.js\n// module id = 123\n// module chunks = 0","'use strict';\n// eslint-disable-next-line es/no-math-expm1 -- safe\nvar $expm1 = Math.expm1;\nvar exp = Math.exp;\n\n// `Math.expm1` method implementation\n// https://tc39.es/ecma262/#sec-math.expm1\nmodule.exports = (!$expm1\n // Old FF bug\n // eslint-disable-next-line no-loss-of-precision -- required for old engines\n || $expm1(10) > 22025.465794806719 || $expm1(10) < 22025.4657948067165168\n // Tor Browser bug\n || $expm1(-2e-17) !== -2e-17\n) ? function expm1(x) {\n var n = +x;\n return n === 0 ? n : n > -1e-6 && n < 1e-6 ? n + n * n / 2 : exp(n) - 1;\n} : $expm1;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/math-expm1.js\n// module id = 124\n// module chunks = 0","'use strict';\n// eslint-disable-next-line es/no-object-getownpropertysymbols -- safe\nexports.f = Object.getOwnPropertySymbols;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/object-get-own-property-symbols.js\n// module id = 125\n// module chunks = 0","'use strict';\nvar $propertyIsEnumerable = {}.propertyIsEnumerable;\n// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe\nvar getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n\n// Nashorn ~ JDK8 bug\nvar NASHORN_BUG = getOwnPropertyDescriptor && !$propertyIsEnumerable.call({ 1: 2 }, 1);\n\n// `Object.prototype.propertyIsEnumerable` method implementation\n// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable\nexports.f = NASHORN_BUG ? function propertyIsEnumerable(V) {\n var descriptor = getOwnPropertyDescriptor(this, V);\n return !!descriptor && descriptor.enumerable;\n} : $propertyIsEnumerable;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/object-property-is-enumerable.js\n// module id = 126\n// module chunks = 0","'use strict';\n/* eslint-disable no-undef, no-useless-call, sonarjs/no-reference-error -- required for testing */\n/* eslint-disable es/no-legacy-object-prototype-accessor-methods -- required for testing */\nvar IS_PURE = require('../internals/is-pure');\nvar globalThis = require('../internals/global-this');\nvar fails = require('../internals/fails');\nvar WEBKIT = require('../internals/environment-webkit-version');\n\n// Forced replacement object prototype accessors methods\nmodule.exports = IS_PURE || !fails(function () {\n // This feature detection crashes old WebKit\n // https://github.com/zloirock/core-js/issues/232\n if (WEBKIT && WEBKIT < 535) return;\n var key = Math.random();\n // In FF throws only define methods\n __defineSetter__.call(null, key, function () { /* empty */ });\n delete globalThis[key];\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/object-prototype-accessors-forced.js\n// module id = 127\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\n\nmodule.exports = globalThis;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/path.js\n// module id = 128\n// module chunks = 0","'use strict';\nvar NativePromiseConstructor = require('../internals/promise-native-constructor');\nvar checkCorrectnessOfIteration = require('../internals/check-correctness-of-iteration');\nvar FORCED_PROMISE_CONSTRUCTOR = require('../internals/promise-constructor-detection').CONSTRUCTOR;\n\nmodule.exports = FORCED_PROMISE_CONSTRUCTOR || !checkCorrectnessOfIteration(function (iterable) {\n NativePromiseConstructor.all(iterable).then(undefined, function () { /* empty */ });\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/promise-statics-incorrect-iteration.js\n// module id = 129\n// module chunks = 0","'use strict';\nvar fails = require('../internals/fails');\nvar globalThis = require('../internals/global-this');\n\n// babel-minify and Closure Compiler transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError\nvar $RegExp = globalThis.RegExp;\n\nvar UNSUPPORTED_Y = fails(function () {\n var re = $RegExp('a', 'y');\n re.lastIndex = 2;\n return re.exec('abcd') !== null;\n});\n\n// UC Browser bug\n// https://github.com/zloirock/core-js/issues/1008\nvar MISSED_STICKY = UNSUPPORTED_Y || fails(function () {\n return !$RegExp('a', 'y').sticky;\n});\n\nvar BROKEN_CARET = UNSUPPORTED_Y || fails(function () {\n // https://bugzilla.mozilla.org/show_bug.cgi?id=773687\n var re = $RegExp('^r', 'gy');\n re.lastIndex = 2;\n return re.exec('str') !== null;\n});\n\nmodule.exports = {\n BROKEN_CARET: BROKEN_CARET,\n MISSED_STICKY: MISSED_STICKY,\n UNSUPPORTED_Y: UNSUPPORTED_Y\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/regexp-sticky-helpers.js\n// module id = 130\n// module chunks = 0","'use strict';\nvar shared = require('../internals/shared');\nvar uid = require('../internals/uid');\n\nvar keys = shared('keys');\n\nmodule.exports = function (key) {\n return keys[key] || (keys[key] = uid(key));\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/shared-key.js\n// module id = 131\n// module chunks = 0","'use strict';\nvar IS_PURE = require('../internals/is-pure');\nvar globalThis = require('../internals/global-this');\nvar defineGlobalProperty = require('../internals/define-global-property');\n\nvar SHARED = '__core-js_shared__';\nvar store = module.exports = globalThis[SHARED] || defineGlobalProperty(SHARED, {});\n\n(store.versions || (store.versions = [])).push({\n version: '3.43.0',\n mode: IS_PURE ? 'pure' : 'global',\n copyright: '© 2014-2025 Denis Pushkarev (zloirock.ru)',\n license: 'https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE',\n source: 'https://github.com/zloirock/core-js'\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/shared-store.js\n// module id = 132\n// module chunks = 0","'use strict';\nvar anObject = require('../internals/an-object');\nvar aConstructor = require('../internals/a-constructor');\nvar isNullOrUndefined = require('../internals/is-null-or-undefined');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\n\nvar SPECIES = wellKnownSymbol('species');\n\n// `SpeciesConstructor` abstract operation\n// https://tc39.es/ecma262/#sec-speciesconstructor\nmodule.exports = function (O, defaultConstructor) {\n var C = anObject(O).constructor;\n var S;\n return C === undefined || isNullOrUndefined(S = anObject(C)[SPECIES]) ? defaultConstructor : aConstructor(S);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/species-constructor.js\n// module id = 133\n// module chunks = 0","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar toIntegerOrInfinity = require('../internals/to-integer-or-infinity');\nvar toString = require('../internals/to-string');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\n\nvar charAt = uncurryThis(''.charAt);\nvar charCodeAt = uncurryThis(''.charCodeAt);\nvar stringSlice = uncurryThis(''.slice);\n\nvar createMethod = function (CONVERT_TO_STRING) {\n return function ($this, pos) {\n var S = toString(requireObjectCoercible($this));\n var position = toIntegerOrInfinity(pos);\n var size = S.length;\n var first, second;\n if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;\n first = charCodeAt(S, position);\n return first < 0xD800 || first > 0xDBFF || position + 1 === size\n || (second = charCodeAt(S, position + 1)) < 0xDC00 || second > 0xDFFF\n ? CONVERT_TO_STRING\n ? charAt(S, position)\n : first\n : CONVERT_TO_STRING\n ? stringSlice(S, position, position + 2)\n : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;\n };\n};\n\nmodule.exports = {\n // `String.prototype.codePointAt` method\n // https://tc39.es/ecma262/#sec-string.prototype.codepointat\n codeAt: createMethod(false),\n // `String.prototype.at` method\n // https://github.com/mathiasbynens/String.prototype.at\n charAt: createMethod(true)\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/string-multibyte.js\n// module id = 134\n// module chunks = 0","'use strict';\n// https://github.com/tc39/proposal-string-pad-start-end\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar toLength = require('../internals/to-length');\nvar toString = require('../internals/to-string');\nvar $repeat = require('../internals/string-repeat');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\n\nvar repeat = uncurryThis($repeat);\nvar stringSlice = uncurryThis(''.slice);\nvar ceil = Math.ceil;\n\n// `String.prototype.{ padStart, padEnd }` methods implementation\nvar createMethod = function (IS_END) {\n return function ($this, maxLength, fillString) {\n var S = toString(requireObjectCoercible($this));\n var intMaxLength = toLength(maxLength);\n var stringLength = S.length;\n var fillStr = fillString === undefined ? ' ' : toString(fillString);\n var fillLen, stringFiller;\n if (intMaxLength <= stringLength || fillStr === '') return S;\n fillLen = intMaxLength - stringLength;\n stringFiller = repeat(fillStr, ceil(fillLen / fillStr.length));\n if (stringFiller.length > fillLen) stringFiller = stringSlice(stringFiller, 0, fillLen);\n return IS_END ? S + stringFiller : stringFiller + S;\n };\n};\n\nmodule.exports = {\n // `String.prototype.padStart` method\n // https://tc39.es/ecma262/#sec-string.prototype.padstart\n start: createMethod(false),\n // `String.prototype.padEnd` method\n // https://tc39.es/ecma262/#sec-string.prototype.padend\n end: createMethod(true)\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/string-pad.js\n// module id = 135\n// module chunks = 0","'use strict';\nvar toIntegerOrInfinity = require('../internals/to-integer-or-infinity');\nvar toString = require('../internals/to-string');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\n\nvar $RangeError = RangeError;\n\n// `String.prototype.repeat` method implementation\n// https://tc39.es/ecma262/#sec-string.prototype.repeat\nmodule.exports = function repeat(count) {\n var str = toString(requireObjectCoercible(this));\n var result = '';\n var n = toIntegerOrInfinity(count);\n if (n < 0 || n === Infinity) throw new $RangeError('Wrong number of repetitions');\n for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) result += str;\n return result;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/string-repeat.js\n// module id = 136\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar apply = require('../internals/function-apply');\nvar bind = require('../internals/function-bind-context');\nvar isCallable = require('../internals/is-callable');\nvar hasOwn = require('../internals/has-own-property');\nvar fails = require('../internals/fails');\nvar html = require('../internals/html');\nvar arraySlice = require('../internals/array-slice');\nvar createElement = require('../internals/document-create-element');\nvar validateArgumentsLength = require('../internals/validate-arguments-length');\nvar IS_IOS = require('../internals/environment-is-ios');\nvar IS_NODE = require('../internals/environment-is-node');\n\nvar set = globalThis.setImmediate;\nvar clear = globalThis.clearImmediate;\nvar process = globalThis.process;\nvar Dispatch = globalThis.Dispatch;\nvar Function = globalThis.Function;\nvar MessageChannel = globalThis.MessageChannel;\nvar String = globalThis.String;\nvar counter = 0;\nvar queue = {};\nvar ONREADYSTATECHANGE = 'onreadystatechange';\nvar $location, defer, channel, port;\n\nfails(function () {\n // Deno throws a ReferenceError on `location` access without `--location` flag\n $location = globalThis.location;\n});\n\nvar run = function (id) {\n if (hasOwn(queue, id)) {\n var fn = queue[id];\n delete queue[id];\n fn();\n }\n};\n\nvar runner = function (id) {\n return function () {\n run(id);\n };\n};\n\nvar eventListener = function (event) {\n run(event.data);\n};\n\nvar globalPostMessageDefer = function (id) {\n // old engines have not location.origin\n globalThis.postMessage(String(id), $location.protocol + '//' + $location.host);\n};\n\n// Node.js 0.9+ & IE10+ has setImmediate, otherwise:\nif (!set || !clear) {\n set = function setImmediate(handler) {\n validateArgumentsLength(arguments.length, 1);\n var fn = isCallable(handler) ? handler : Function(handler);\n var args = arraySlice(arguments, 1);\n queue[++counter] = function () {\n apply(fn, undefined, args);\n };\n defer(counter);\n return counter;\n };\n clear = function clearImmediate(id) {\n delete queue[id];\n };\n // Node.js 0.8-\n if (IS_NODE) {\n defer = function (id) {\n process.nextTick(runner(id));\n };\n // Sphere (JS game engine) Dispatch API\n } else if (Dispatch && Dispatch.now) {\n defer = function (id) {\n Dispatch.now(runner(id));\n };\n // Browsers with MessageChannel, includes WebWorkers\n // except iOS - https://github.com/zloirock/core-js/issues/624\n } else if (MessageChannel && !IS_IOS) {\n channel = new MessageChannel();\n port = channel.port2;\n channel.port1.onmessage = eventListener;\n defer = bind(port.postMessage, port);\n // Browsers with postMessage, skip WebWorkers\n // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'\n } else if (\n globalThis.addEventListener &&\n isCallable(globalThis.postMessage) &&\n !globalThis.importScripts &&\n $location && $location.protocol !== 'file:' &&\n !fails(globalPostMessageDefer)\n ) {\n defer = globalPostMessageDefer;\n globalThis.addEventListener('message', eventListener, false);\n // IE8-\n } else if (ONREADYSTATECHANGE in createElement('script')) {\n defer = function (id) {\n html.appendChild(createElement('script'))[ONREADYSTATECHANGE] = function () {\n html.removeChild(this);\n run(id);\n };\n };\n // Rest old browsers\n } else {\n defer = function (id) {\n setTimeout(runner(id), 0);\n };\n }\n}\n\nmodule.exports = {\n set: set,\n clear: clear\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/task.js\n// module id = 137\n// module chunks = 0","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\n\n// `thisNumberValue` abstract operation\n// https://tc39.es/ecma262/#sec-thisnumbervalue\nmodule.exports = uncurryThis(1.1.valueOf);\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/this-number-value.js\n// module id = 138\n// module chunks = 0","'use strict';\nvar toIntegerOrInfinity = require('../internals/to-integer-or-infinity');\nvar toLength = require('../internals/to-length');\n\nvar $RangeError = RangeError;\n\n// `ToIndex` abstract operation\n// https://tc39.es/ecma262/#sec-toindex\nmodule.exports = function (it) {\n if (it === undefined) return 0;\n var number = toIntegerOrInfinity(it);\n var length = toLength(number);\n if (number !== length) throw new $RangeError('Wrong length or index');\n return length;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/to-index.js\n// module id = 139\n// module chunks = 0","'use strict';\nvar call = require('../internals/function-call');\nvar isObject = require('../internals/is-object');\nvar isSymbol = require('../internals/is-symbol');\nvar getMethod = require('../internals/get-method');\nvar ordinaryToPrimitive = require('../internals/ordinary-to-primitive');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\n\nvar $TypeError = TypeError;\nvar TO_PRIMITIVE = wellKnownSymbol('toPrimitive');\n\n// `ToPrimitive` abstract operation\n// https://tc39.es/ecma262/#sec-toprimitive\nmodule.exports = function (input, pref) {\n if (!isObject(input) || isSymbol(input)) return input;\n var exoticToPrim = getMethod(input, TO_PRIMITIVE);\n var result;\n if (exoticToPrim) {\n if (pref === undefined) pref = 'default';\n result = call(exoticToPrim, input, pref);\n if (!isObject(result) || isSymbol(result)) return result;\n throw new $TypeError(\"Can't convert object to primitive value\");\n }\n if (pref === undefined) pref = 'number';\n return ordinaryToPrimitive(input, pref);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/to-primitive.js\n// module id = 140\n// module chunks = 0","'use strict';\nvar fails = require('../internals/fails');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\nvar DESCRIPTORS = require('../internals/descriptors');\nvar IS_PURE = require('../internals/is-pure');\n\nvar ITERATOR = wellKnownSymbol('iterator');\n\nmodule.exports = !fails(function () {\n // eslint-disable-next-line unicorn/relative-url-style -- required for testing\n var url = new URL('b?a=1&b=2&c=3', 'https://a');\n var params = url.searchParams;\n var params2 = new URLSearchParams('a=1&a=2&b=3');\n var result = '';\n url.pathname = 'c%20d';\n params.forEach(function (value, key) {\n params['delete']('b');\n result += key + value;\n });\n params2['delete']('a', 2);\n // `undefined` case is a Chromium 117 bug\n // https://bugs.chromium.org/p/v8/issues/detail?id=14222\n params2['delete']('b', undefined);\n return (IS_PURE && (!url.toJSON || !params2.has('a', 1) || params2.has('a', 2) || !params2.has('a', undefined) || params2.has('b')))\n || (!params.size && (IS_PURE || !DESCRIPTORS))\n || !params.sort\n || url.href !== 'https://a/c%20d?a=1&c=3'\n || params.get('c') !== '3'\n || String(new URLSearchParams('?a=1')) !== 'a=1'\n || !params[ITERATOR]\n // throws in Edge\n || new URL('https://a@b').username !== 'a'\n || new URLSearchParams(new URLSearchParams('a=b')).get('a') !== 'b'\n // not punycoded in Edge\n || new URL('https://тест').host !== 'xn--e1aybc'\n // not escaped in Chrome 62-\n || new URL('https://a#б').hash !== '#%D0%B1'\n // fails in Chrome 66-\n || result !== 'a1c3'\n // throws in Safari\n || new URL('https://x', undefined).host !== 'x';\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/url-constructor-detection.js\n// module id = 141\n// module chunks = 0","'use strict';\nvar toIndexedObject = require('../internals/to-indexed-object');\nvar addToUnscopables = require('../internals/add-to-unscopables');\nvar Iterators = require('../internals/iterators');\nvar InternalStateModule = require('../internals/internal-state');\nvar defineProperty = require('../internals/object-define-property').f;\nvar defineIterator = require('../internals/iterator-define');\nvar createIterResultObject = require('../internals/create-iter-result-object');\nvar IS_PURE = require('../internals/is-pure');\nvar DESCRIPTORS = require('../internals/descriptors');\n\nvar ARRAY_ITERATOR = 'Array Iterator';\nvar setInternalState = InternalStateModule.set;\nvar getInternalState = InternalStateModule.getterFor(ARRAY_ITERATOR);\n\n// `Array.prototype.entries` method\n// https://tc39.es/ecma262/#sec-array.prototype.entries\n// `Array.prototype.keys` method\n// https://tc39.es/ecma262/#sec-array.prototype.keys\n// `Array.prototype.values` method\n// https://tc39.es/ecma262/#sec-array.prototype.values\n// `Array.prototype[@@iterator]` method\n// https://tc39.es/ecma262/#sec-array.prototype-@@iterator\n// `CreateArrayIterator` internal method\n// https://tc39.es/ecma262/#sec-createarrayiterator\nmodule.exports = defineIterator(Array, 'Array', function (iterated, kind) {\n setInternalState(this, {\n type: ARRAY_ITERATOR,\n target: toIndexedObject(iterated), // target\n index: 0, // next index\n kind: kind // kind\n });\n// `%ArrayIteratorPrototype%.next` method\n// https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next\n}, function () {\n var state = getInternalState(this);\n var target = state.target;\n var index = state.index++;\n if (!target || index >= target.length) {\n state.target = null;\n return createIterResultObject(undefined, true);\n }\n switch (state.kind) {\n case 'keys': return createIterResultObject(index, false);\n case 'values': return createIterResultObject(target[index], false);\n } return createIterResultObject([index, target[index]], false);\n}, 'values');\n\n// argumentsList[@@iterator] is %ArrayProto_values%\n// https://tc39.es/ecma262/#sec-createunmappedargumentsobject\n// https://tc39.es/ecma262/#sec-createmappedargumentsobject\nvar values = Iterators.Arguments = Iterators.Array;\n\n// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables\naddToUnscopables('keys');\naddToUnscopables('values');\naddToUnscopables('entries');\n\n// V8 ~ Chrome 45- bug\nif (!IS_PURE && DESCRIPTORS && values.name !== 'values') try {\n defineProperty(values, 'name', { value: 'values' });\n} catch (error) { /* empty */ }\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es.array.iterator.js\n// module id = 142\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.requestAudioContext = exports.intervalInRange = exports.roundInterval = exports.clamp = exports.lerp = exports.browser = 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\n/**\n * Utilities\n * @module lib/util.js;\n */\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 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 roundInterval(interval) {\n return Math.round(interval * 10000000);\n}\nvar intervalInRange = function intervalInRange(interval, root) {\n return 20 < interval * root && interval * root < 15000;\n};\nvar lerp = function lerp(n, a, b) {\n return (b - a) * n + a;\n};\nvar clamp = function clamp(n) {\n var a = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n var b = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;\n return n < a ? a : n < b ? n : b;\n};\n\nfunction requestAudioContext(fn) {\n if (window.location.protocol !== \"https:\") {\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.browser = browser;\nexports.lerp = lerp;\nexports.clamp = clamp;\nexports.roundInterval = roundInterval;\nexports.intervalInRange = intervalInRange;\nexports.requestAudioContext = requestAudioContext;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/util.js\n// module id = 143\n// module chunks = 0","'use strict';\nvar isConstructor = require('../internals/is-constructor');\nvar tryToString = require('../internals/try-to-string');\n\nvar $TypeError = TypeError;\n\n// `Assert: IsConstructor(argument) is true`\nmodule.exports = function (argument) {\n if (isConstructor(argument)) return argument;\n throw new $TypeError(tryToString(argument) + ' is not a constructor');\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/a-constructor.js\n// module id = 144\n// module chunks = 0","'use strict';\n// FF26- bug: ArrayBuffers are non-extensible, but Object.isExtensible does not report it\nvar fails = require('../internals/fails');\n\nmodule.exports = fails(function () {\n if (typeof ArrayBuffer == 'function') {\n var buffer = new ArrayBuffer(8);\n // eslint-disable-next-line es/no-object-isextensible, es/no-object-defineproperty -- safe\n if (Object.isExtensible(buffer)) Object.defineProperty(buffer, 'a', { value: 8 });\n }\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-buffer-non-extensible.js\n// module id = 145\n// module chunks = 0","'use strict';\nvar toObject = require('../internals/to-object');\nvar toAbsoluteIndex = require('../internals/to-absolute-index');\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\n\n// `Array.prototype.fill` method implementation\n// https://tc39.es/ecma262/#sec-array.prototype.fill\nmodule.exports = function fill(value /* , start = 0, end = @length */) {\n var O = toObject(this);\n var length = lengthOfArrayLike(O);\n var argumentsLength = arguments.length;\n var index = toAbsoluteIndex(argumentsLength > 1 ? arguments[1] : undefined, length);\n var end = argumentsLength > 2 ? arguments[2] : undefined;\n var endPos = end === undefined ? length : toAbsoluteIndex(end, length);\n while (endPos > index) O[index++] = value;\n return O;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-fill.js\n// module id = 146\n// module chunks = 0","'use strict';\nvar DESCRIPTORS = require('../internals/descriptors');\nvar isArray = require('../internals/is-array');\n\nvar $TypeError = TypeError;\n// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe\nvar getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n\n// Safari < 13 does not throw an error in this case\nvar SILENT_ON_NON_WRITABLE_LENGTH_SET = DESCRIPTORS && !function () {\n // makes no sense without proper strict mode support\n if (this !== undefined) return true;\n try {\n // eslint-disable-next-line es/no-object-defineproperty -- safe\n Object.defineProperty([], 'length', { writable: false }).length = 1;\n } catch (error) {\n return error instanceof TypeError;\n }\n}();\n\nmodule.exports = SILENT_ON_NON_WRITABLE_LENGTH_SET ? function (O, length) {\n if (isArray(O) && !getOwnPropertyDescriptor(O, 'length').writable) {\n throw new $TypeError('Cannot set read only .length');\n } return O.length = length;\n} : function (O, length) {\n return O.length = length;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-set-length.js\n// module id = 147\n// module chunks = 0","'use strict';\nvar arraySlice = require('../internals/array-slice');\n\nvar floor = Math.floor;\n\nvar sort = function (array, comparefn) {\n var length = array.length;\n\n if (length < 8) {\n // insertion sort\n var i = 1;\n var element, j;\n\n while (i < length) {\n j = i;\n element = array[i];\n while (j && comparefn(array[j - 1], element) > 0) {\n array[j] = array[--j];\n }\n if (j !== i++) array[j] = element;\n }\n } else {\n // merge sort\n var middle = floor(length / 2);\n var left = sort(arraySlice(array, 0, middle), comparefn);\n var right = sort(arraySlice(array, middle), comparefn);\n var llength = left.length;\n var rlength = right.length;\n var lindex = 0;\n var rindex = 0;\n\n while (lindex < llength || rindex < rlength) {\n array[lindex + rindex] = (lindex < llength && rindex < rlength)\n ? comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++]\n : lindex < llength ? left[lindex++] : right[rindex++];\n }\n }\n\n return array;\n};\n\nmodule.exports = sort;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-sort.js\n// module id = 148\n// module chunks = 0","'use strict';\nvar anObject = require('../internals/an-object');\nvar iteratorClose = require('../internals/iterator-close');\n\n// call something on iterator step with safe closing on error\nmodule.exports = function (iterator, fn, value, ENTRIES) {\n try {\n return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value);\n } catch (error) {\n iteratorClose(iterator, 'throw', error);\n }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/call-with-safe-iteration-closing.js\n// module id = 149\n// module chunks = 0","'use strict';\nvar wellKnownSymbol = require('../internals/well-known-symbol');\n\nvar MATCH = wellKnownSymbol('match');\n\nmodule.exports = function (METHOD_NAME) {\n var regexp = /./;\n try {\n '/./'[METHOD_NAME](regexp);\n } catch (error1) {\n try {\n regexp[MATCH] = false;\n return '/./'[METHOD_NAME](regexp);\n } catch (error2) { /* empty */ }\n } return false;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/correct-is-regexp-logic.js\n// module id = 150\n// module chunks = 0","'use strict';\nvar fails = require('../internals/fails');\n\nmodule.exports = !fails(function () {\n function F() { /* empty */ }\n F.prototype.constructor = null;\n // eslint-disable-next-line es/no-object-getprototypeof -- required for testing\n return Object.getPrototypeOf(new F()) !== F.prototype;\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/correct-prototype-getter.js\n// module id = 151\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\n\n// eslint-disable-next-line es/no-object-defineproperty -- safe\nvar defineProperty = Object.defineProperty;\n\nmodule.exports = function (key, value) {\n try {\n defineProperty(globalThis, key, { value: value, configurable: true, writable: true });\n } catch (error) {\n globalThis[key] = value;\n } return value;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/define-global-property.js\n// module id = 152\n// module chunks = 0","'use strict';\n// IE8- don't enum bug keys\nmodule.exports = [\n 'constructor',\n 'hasOwnProperty',\n 'isPrototypeOf',\n 'propertyIsEnumerable',\n 'toLocaleString',\n 'toString',\n 'valueOf'\n];\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/enum-bug-keys.js\n// module id = 153\n// module chunks = 0","'use strict';\nvar userAgent = require('../internals/environment-user-agent');\n\nvar webkit = userAgent.match(/AppleWebKit\\/(\\d+)\\./);\n\nmodule.exports = !!webkit && +webkit[1];\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/environment-webkit-version.js\n// module id = 154\n// module chunks = 0","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\n\nvar $Error = Error;\nvar replace = uncurryThis(''.replace);\n\nvar TEST = (function (arg) { return String(new $Error(arg).stack); })('zxcasd');\n// eslint-disable-next-line redos/no-vulnerable, sonarjs/slow-regex -- safe\nvar V8_OR_CHAKRA_STACK_ENTRY = /\\n\\s*at [^:]*:[^\\n]*/;\nvar IS_V8_OR_CHAKRA_STACK = V8_OR_CHAKRA_STACK_ENTRY.test(TEST);\n\nmodule.exports = function (stack, dropEntries) {\n if (IS_V8_OR_CHAKRA_STACK && typeof stack == 'string' && !$Error.prepareStackTrace) {\n while (dropEntries--) stack = replace(stack, V8_OR_CHAKRA_STACK_ENTRY, '');\n } return stack;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/error-stack-clear.js\n// module id = 155\n// module chunks = 0","'use strict';\nvar createNonEnumerableProperty = require('../internals/create-non-enumerable-property');\nvar clearErrorStack = require('../internals/error-stack-clear');\nvar ERROR_STACK_INSTALLABLE = require('../internals/error-stack-installable');\n\n// non-standard V8\n// eslint-disable-next-line es/no-nonstandard-error-properties -- safe\nvar captureStackTrace = Error.captureStackTrace;\n\nmodule.exports = function (error, C, stack, dropEntries) {\n if (ERROR_STACK_INSTALLABLE) {\n if (captureStackTrace) captureStackTrace(error, C);\n else createNonEnumerableProperty(error, 'stack', clearErrorStack(stack, dropEntries));\n }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/error-stack-install.js\n// module id = 156\n// module chunks = 0","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar isCallable = require('../internals/is-callable');\nvar store = require('../internals/shared-store');\n\nvar functionToString = uncurryThis(Function.toString);\n\n// this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper\nif (!isCallable(store.inspectSource)) {\n store.inspectSource = function (it) {\n return functionToString(it);\n };\n}\n\nmodule.exports = store.inspectSource;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/inspect-source.js\n// module id = 157\n// module chunks = 0","'use strict';\nvar wellKnownSymbol = require('../internals/well-known-symbol');\nvar Iterators = require('../internals/iterators');\n\nvar ITERATOR = wellKnownSymbol('iterator');\nvar ArrayPrototype = Array.prototype;\n\n// check on default Array iterator\nmodule.exports = function (it) {\n return it !== undefined && (Iterators.Array === it || ArrayPrototype[ITERATOR] === it);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/is-array-iterator-method.js\n// module id = 158\n// module chunks = 0","'use strict';\nvar isObject = require('../internals/is-object');\n\nvar floor = Math.floor;\n\n// `IsIntegralNumber` abstract operation\n// https://tc39.es/ecma262/#sec-isintegralnumber\n// eslint-disable-next-line es/no-number-isinteger -- safe\nmodule.exports = Number.isInteger || function isInteger(it) {\n return !isObject(it) && isFinite(it) && floor(it) === it;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/is-integral-number.js\n// module id = 159\n// module chunks = 0","'use strict';\nvar IteratorPrototype = require('../internals/iterators-core').IteratorPrototype;\nvar create = require('../internals/object-create');\nvar createPropertyDescriptor = require('../internals/create-property-descriptor');\nvar setToStringTag = require('../internals/set-to-string-tag');\nvar Iterators = require('../internals/iterators');\n\nvar returnThis = function () { return this; };\n\nmodule.exports = function (IteratorConstructor, NAME, next, ENUMERABLE_NEXT) {\n var TO_STRING_TAG = NAME + ' Iterator';\n IteratorConstructor.prototype = create(IteratorPrototype, { next: createPropertyDescriptor(+!ENUMERABLE_NEXT, next) });\n setToStringTag(IteratorConstructor, TO_STRING_TAG, false, true);\n Iterators[TO_STRING_TAG] = returnThis;\n return IteratorConstructor;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/iterator-create-constructor.js\n// module id = 160\n// module chunks = 0","'use strict';\nvar $ = require('../internals/export');\nvar call = require('../internals/function-call');\nvar IS_PURE = require('../internals/is-pure');\nvar FunctionName = require('../internals/function-name');\nvar isCallable = require('../internals/is-callable');\nvar createIteratorConstructor = require('../internals/iterator-create-constructor');\nvar getPrototypeOf = require('../internals/object-get-prototype-of');\nvar setPrototypeOf = require('../internals/object-set-prototype-of');\nvar setToStringTag = require('../internals/set-to-string-tag');\nvar createNonEnumerableProperty = require('../internals/create-non-enumerable-property');\nvar defineBuiltIn = require('../internals/define-built-in');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\nvar Iterators = require('../internals/iterators');\nvar IteratorsCore = require('../internals/iterators-core');\n\nvar PROPER_FUNCTION_NAME = FunctionName.PROPER;\nvar CONFIGURABLE_FUNCTION_NAME = FunctionName.CONFIGURABLE;\nvar IteratorPrototype = IteratorsCore.IteratorPrototype;\nvar BUGGY_SAFARI_ITERATORS = IteratorsCore.BUGGY_SAFARI_ITERATORS;\nvar ITERATOR = wellKnownSymbol('iterator');\nvar KEYS = 'keys';\nvar VALUES = 'values';\nvar ENTRIES = 'entries';\n\nvar returnThis = function () { return this; };\n\nmodule.exports = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {\n createIteratorConstructor(IteratorConstructor, NAME, next);\n\n var getIterationMethod = function (KIND) {\n if (KIND === DEFAULT && defaultIterator) return defaultIterator;\n if (!BUGGY_SAFARI_ITERATORS && KIND && KIND in IterablePrototype) return IterablePrototype[KIND];\n\n switch (KIND) {\n case KEYS: return function keys() { return new IteratorConstructor(this, KIND); };\n case VALUES: return function values() { return new IteratorConstructor(this, KIND); };\n case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); };\n }\n\n return function () { return new IteratorConstructor(this); };\n };\n\n var TO_STRING_TAG = NAME + ' Iterator';\n var INCORRECT_VALUES_NAME = false;\n var IterablePrototype = Iterable.prototype;\n var nativeIterator = IterablePrototype[ITERATOR]\n || IterablePrototype['@@iterator']\n || DEFAULT && IterablePrototype[DEFAULT];\n var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT);\n var anyNativeIterator = NAME === 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;\n var CurrentIteratorPrototype, methods, KEY;\n\n // fix native\n if (anyNativeIterator) {\n CurrentIteratorPrototype = getPrototypeOf(anyNativeIterator.call(new Iterable()));\n if (CurrentIteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {\n if (!IS_PURE && getPrototypeOf(CurrentIteratorPrototype) !== IteratorPrototype) {\n if (setPrototypeOf) {\n setPrototypeOf(CurrentIteratorPrototype, IteratorPrototype);\n } else if (!isCallable(CurrentIteratorPrototype[ITERATOR])) {\n defineBuiltIn(CurrentIteratorPrototype, ITERATOR, returnThis);\n }\n }\n // Set @@toStringTag to native iterators\n setToStringTag(CurrentIteratorPrototype, TO_STRING_TAG, true, true);\n if (IS_PURE) Iterators[TO_STRING_TAG] = returnThis;\n }\n }\n\n // fix Array.prototype.{ values, @@iterator }.name in V8 / FF\n if (PROPER_FUNCTION_NAME && DEFAULT === VALUES && nativeIterator && nativeIterator.name !== VALUES) {\n if (!IS_PURE && CONFIGURABLE_FUNCTION_NAME) {\n createNonEnumerableProperty(IterablePrototype, 'name', VALUES);\n } else {\n INCORRECT_VALUES_NAME = true;\n defaultIterator = function values() { return call(nativeIterator, this); };\n }\n }\n\n // export additional methods\n if (DEFAULT) {\n methods = {\n values: getIterationMethod(VALUES),\n keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),\n entries: getIterationMethod(ENTRIES)\n };\n if (FORCED) for (KEY in methods) {\n if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {\n defineBuiltIn(IterablePrototype, KEY, methods[KEY]);\n }\n } else $({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);\n }\n\n // define iterator\n if ((!IS_PURE || FORCED) && IterablePrototype[ITERATOR] !== defaultIterator) {\n defineBuiltIn(IterablePrototype, ITERATOR, defaultIterator, { name: DEFAULT });\n }\n Iterators[NAME] = defaultIterator;\n\n return methods;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/iterator-define.js\n// module id = 161\n// module chunks = 0","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar fails = require('../internals/fails');\nvar isCallable = require('../internals/is-callable');\nvar hasOwn = require('../internals/has-own-property');\nvar DESCRIPTORS = require('../internals/descriptors');\nvar CONFIGURABLE_FUNCTION_NAME = require('../internals/function-name').CONFIGURABLE;\nvar inspectSource = require('../internals/inspect-source');\nvar InternalStateModule = require('../internals/internal-state');\n\nvar enforceInternalState = InternalStateModule.enforce;\nvar getInternalState = InternalStateModule.get;\nvar $String = String;\n// eslint-disable-next-line es/no-object-defineproperty -- safe\nvar defineProperty = Object.defineProperty;\nvar stringSlice = uncurryThis(''.slice);\nvar replace = uncurryThis(''.replace);\nvar join = uncurryThis([].join);\n\nvar CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function () {\n return defineProperty(function () { /* empty */ }, 'length', { value: 8 }).length !== 8;\n});\n\nvar TEMPLATE = String(String).split('String');\n\nvar makeBuiltIn = module.exports = function (value, name, options) {\n if (stringSlice($String(name), 0, 7) === 'Symbol(') {\n name = '[' + replace($String(name), /^Symbol\\(([^)]*)\\).*$/, '$1') + ']';\n }\n if (options && options.getter) name = 'get ' + name;\n if (options && options.setter) name = 'set ' + name;\n if (!hasOwn(value, 'name') || (CONFIGURABLE_FUNCTION_NAME && value.name !== name)) {\n if (DESCRIPTORS) defineProperty(value, 'name', { value: name, configurable: true });\n else value.name = name;\n }\n if (CONFIGURABLE_LENGTH && options && hasOwn(options, 'arity') && value.length !== options.arity) {\n defineProperty(value, 'length', { value: options.arity });\n }\n try {\n if (options && hasOwn(options, 'constructor') && options.constructor) {\n if (DESCRIPTORS) defineProperty(value, 'prototype', { writable: false });\n // in V8 ~ Chrome 53, prototypes of some methods, like `Array.prototype.values`, are non-writable\n } else if (value.prototype) value.prototype = undefined;\n } catch (error) { /* empty */ }\n var state = enforceInternalState(value);\n if (!hasOwn(state, 'source')) {\n state.source = join(TEMPLATE, typeof name == 'string' ? name : '');\n } return value;\n};\n\n// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative\n// eslint-disable-next-line no-extend-native -- required\nFunction.prototype.toString = makeBuiltIn(function toString() {\n return isCallable(this) && getInternalState(this).source || inspectSource(this);\n}, 'toString');\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/make-built-in.js\n// module id = 162\n// module chunks = 0","'use strict';\n// `Math.sign` method implementation\n// https://tc39.es/ecma262/#sec-math.sign\n// eslint-disable-next-line es/no-math-sign -- safe\nmodule.exports = Math.sign || function sign(x) {\n var n = +x;\n // eslint-disable-next-line no-self-compare -- NaN check\n return n === 0 || n !== n ? n : n < 0 ? -1 : 1;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/math-sign.js\n// module id = 163\n// module chunks = 0","'use strict';\nvar isRegExp = require('../internals/is-regexp');\n\nvar $TypeError = TypeError;\n\nmodule.exports = function (it) {\n if (isRegExp(it)) {\n throw new $TypeError(\"The method doesn't accept regular expressions\");\n } return it;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/not-a-regexp.js\n// module id = 164\n// module chunks = 0","'use strict';\nvar DESCRIPTORS = require('../internals/descriptors');\nvar V8_PROTOTYPE_DEFINE_BUG = require('../internals/v8-prototype-define-bug');\nvar definePropertyModule = require('../internals/object-define-property');\nvar anObject = require('../internals/an-object');\nvar toIndexedObject = require('../internals/to-indexed-object');\nvar objectKeys = require('../internals/object-keys');\n\n// `Object.defineProperties` method\n// https://tc39.es/ecma262/#sec-object.defineproperties\n// eslint-disable-next-line es/no-object-defineproperties -- safe\nexports.f = DESCRIPTORS && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) {\n anObject(O);\n var props = toIndexedObject(Properties);\n var keys = objectKeys(Properties);\n var length = keys.length;\n var index = 0;\n var key;\n while (length > index) definePropertyModule.f(O, key = keys[index++], props[key]);\n return O;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/object-define-properties.js\n// module id = 165\n// module chunks = 0","'use strict';\n/* eslint-disable es/no-object-getownpropertynames -- safe */\nvar classof = require('../internals/classof-raw');\nvar toIndexedObject = require('../internals/to-indexed-object');\nvar $getOwnPropertyNames = require('../internals/object-get-own-property-names').f;\nvar arraySlice = require('../internals/array-slice');\n\nvar windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames\n ? Object.getOwnPropertyNames(window) : [];\n\nvar getWindowNames = function (it) {\n try {\n return $getOwnPropertyNames(it);\n } catch (error) {\n return arraySlice(windowNames);\n }\n};\n\n// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window\nmodule.exports.f = function getOwnPropertyNames(it) {\n return windowNames && classof(it) === 'Window'\n ? getWindowNames(it)\n : $getOwnPropertyNames(toIndexedObject(it));\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/object-get-own-property-names-external.js\n// module id = 166\n// module chunks = 0","'use strict';\nvar fails = require('../internals/fails');\nvar isObject = require('../internals/is-object');\nvar classof = require('../internals/classof-raw');\nvar ARRAY_BUFFER_NON_EXTENSIBLE = require('../internals/array-buffer-non-extensible');\n\n// eslint-disable-next-line es/no-object-isextensible -- safe\nvar $isExtensible = Object.isExtensible;\nvar FAILS_ON_PRIMITIVES = fails(function () { $isExtensible(1); });\n\n// `Object.isExtensible` method\n// https://tc39.es/ecma262/#sec-object.isextensible\nmodule.exports = (FAILS_ON_PRIMITIVES || ARRAY_BUFFER_NON_EXTENSIBLE) ? function isExtensible(it) {\n if (!isObject(it)) return false;\n if (ARRAY_BUFFER_NON_EXTENSIBLE && classof(it) === 'ArrayBuffer') return false;\n return $isExtensible ? $isExtensible(it) : true;\n} : $isExtensible;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/object-is-extensible.js\n// module id = 167\n// module chunks = 0","'use strict';\nvar getBuiltIn = require('../internals/get-built-in');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar getOwnPropertyNamesModule = require('../internals/object-get-own-property-names');\nvar getOwnPropertySymbolsModule = require('../internals/object-get-own-property-symbols');\nvar anObject = require('../internals/an-object');\n\nvar concat = uncurryThis([].concat);\n\n// all object keys, includes non-enumerable and symbols\nmodule.exports = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {\n var keys = getOwnPropertyNamesModule.f(anObject(it));\n var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;\n return getOwnPropertySymbols ? concat(keys, getOwnPropertySymbols(it)) : keys;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/own-keys.js\n// module id = 168\n// module chunks = 0","'use strict';\n/* eslint-disable regexp/no-empty-capturing-group, regexp/no-empty-group, regexp/no-lazy-ends -- testing */\n/* eslint-disable regexp/no-useless-quantifier -- testing */\nvar call = require('../internals/function-call');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar toString = require('../internals/to-string');\nvar regexpFlags = require('../internals/regexp-flags');\nvar stickyHelpers = require('../internals/regexp-sticky-helpers');\nvar shared = require('../internals/shared');\nvar create = require('../internals/object-create');\nvar getInternalState = require('../internals/internal-state').get;\nvar UNSUPPORTED_DOT_ALL = require('../internals/regexp-unsupported-dot-all');\nvar UNSUPPORTED_NCG = require('../internals/regexp-unsupported-ncg');\n\nvar nativeReplace = shared('native-string-replace', String.prototype.replace);\nvar nativeExec = RegExp.prototype.exec;\nvar patchedExec = nativeExec;\nvar charAt = uncurryThis(''.charAt);\nvar indexOf = uncurryThis(''.indexOf);\nvar replace = uncurryThis(''.replace);\nvar stringSlice = uncurryThis(''.slice);\n\nvar UPDATES_LAST_INDEX_WRONG = (function () {\n var re1 = /a/;\n var re2 = /b*/g;\n call(nativeExec, re1, 'a');\n call(nativeExec, re2, 'a');\n return re1.lastIndex !== 0 || re2.lastIndex !== 0;\n})();\n\nvar UNSUPPORTED_Y = stickyHelpers.BROKEN_CARET;\n\n// nonparticipating capturing group, copied from es5-shim's String#split patch.\nvar NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;\n\nvar PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y || UNSUPPORTED_DOT_ALL || UNSUPPORTED_NCG;\n\nif (PATCH) {\n patchedExec = function exec(string) {\n var re = this;\n var state = getInternalState(re);\n var str = toString(string);\n var raw = state.raw;\n var result, reCopy, lastIndex, match, i, object, group;\n\n if (raw) {\n raw.lastIndex = re.lastIndex;\n result = call(patchedExec, raw, str);\n re.lastIndex = raw.lastIndex;\n return result;\n }\n\n var groups = state.groups;\n var sticky = UNSUPPORTED_Y && re.sticky;\n var flags = call(regexpFlags, re);\n var source = re.source;\n var charsAdded = 0;\n var strCopy = str;\n\n if (sticky) {\n flags = replace(flags, 'y', '');\n if (indexOf(flags, 'g') === -1) {\n flags += 'g';\n }\n\n strCopy = stringSlice(str, re.lastIndex);\n // Support anchored sticky behavior.\n if (re.lastIndex > 0 && (!re.multiline || re.multiline && charAt(str, re.lastIndex - 1) !== '\\n')) {\n source = '(?: ' + source + ')';\n strCopy = ' ' + strCopy;\n charsAdded++;\n }\n // ^(? + rx + ) is needed, in combination with some str slicing, to\n // simulate the 'y' flag.\n reCopy = new RegExp('^(?:' + source + ')', flags);\n }\n\n if (NPCG_INCLUDED) {\n reCopy = new RegExp('^' + source + '$(?!\\\\s)', flags);\n }\n if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex;\n\n match = call(nativeExec, sticky ? reCopy : re, strCopy);\n\n if (sticky) {\n if (match) {\n match.input = stringSlice(match.input, charsAdded);\n match[0] = stringSlice(match[0], charsAdded);\n match.index = re.lastIndex;\n re.lastIndex += match[0].length;\n } else re.lastIndex = 0;\n } else if (UPDATES_LAST_INDEX_WRONG && match) {\n re.lastIndex = re.global ? match.index + match[0].length : lastIndex;\n }\n if (NPCG_INCLUDED && match && match.length > 1) {\n // Fix browsers whose `exec` methods don't consistently return `undefined`\n // for NPCG, like IE8. NOTE: This doesn't work for /(.?)?/\n call(nativeReplace, match[0], reCopy, function () {\n for (i = 1; i < arguments.length - 2; i++) {\n if (arguments[i] === undefined) match[i] = undefined;\n }\n });\n }\n\n if (match && groups) {\n match.groups = object = create(null);\n for (i = 0; i < groups.length; i++) {\n group = groups[i];\n object[group[0]] = match[group[1]];\n }\n }\n\n return match;\n };\n}\n\nmodule.exports = patchedExec;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/regexp-exec.js\n// module id = 169\n// module chunks = 0","'use strict';\nvar anObject = require('../internals/an-object');\n\n// `RegExp.prototype.flags` getter implementation\n// https://tc39.es/ecma262/#sec-get-regexp.prototype.flags\nmodule.exports = function () {\n var that = anObject(this);\n var result = '';\n if (that.hasIndices) result += 'd';\n if (that.global) result += 'g';\n if (that.ignoreCase) result += 'i';\n if (that.multiline) result += 'm';\n if (that.dotAll) result += 's';\n if (that.unicode) result += 'u';\n if (that.unicodeSets) result += 'v';\n if (that.sticky) result += 'y';\n return result;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/regexp-flags.js\n// module id = 170\n// module chunks = 0","'use strict';\nvar fails = require('../internals/fails');\nvar globalThis = require('../internals/global-this');\n\n// babel-minify and Closure Compiler transpiles RegExp('.', 's') -> /./s and it causes SyntaxError\nvar $RegExp = globalThis.RegExp;\n\nmodule.exports = fails(function () {\n var re = $RegExp('.', 's');\n return !(re.dotAll && re.test('\\n') && re.flags === 's');\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/regexp-unsupported-dot-all.js\n// module id = 171\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar apply = require('../internals/function-apply');\nvar isCallable = require('../internals/is-callable');\nvar ENVIRONMENT = require('../internals/environment');\nvar USER_AGENT = require('../internals/environment-user-agent');\nvar arraySlice = require('../internals/array-slice');\nvar validateArgumentsLength = require('../internals/validate-arguments-length');\n\nvar Function = globalThis.Function;\n// dirty IE9- and Bun 0.3.0- checks\nvar WRAP = /MSIE .\\./.test(USER_AGENT) || ENVIRONMENT === 'BUN' && (function () {\n var version = globalThis.Bun.version.split('.');\n return version.length < 3 || version[0] === '0' && (version[1] < 3 || version[1] === '3' && version[2] === '0');\n})();\n\n// IE9- / Bun 0.3.0- setTimeout / setInterval / setImmediate additional parameters fix\n// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers\n// https://github.com/oven-sh/bun/issues/1633\nmodule.exports = function (scheduler, hasTimeArg) {\n var firstParamIndex = hasTimeArg ? 2 : 1;\n return WRAP ? function (handler, timeout /* , ...arguments */) {\n var boundArgs = validateArgumentsLength(arguments.length, 1) > firstParamIndex;\n var fn = isCallable(handler) ? handler : Function(handler);\n var params = boundArgs ? arraySlice(arguments, firstParamIndex) : [];\n var callback = boundArgs ? function () {\n apply(fn, this, params);\n } : fn;\n return hasTimeArg ? scheduler(callback, timeout) : scheduler(callback);\n } : scheduler;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/schedulers-fix.js\n// module id = 172\n// module chunks = 0","'use strict';\nvar SetHelpers = require('../internals/set-helpers');\nvar iterate = require('../internals/set-iterate');\n\nvar Set = SetHelpers.Set;\nvar add = SetHelpers.add;\n\nmodule.exports = function (set) {\n var result = new Set();\n iterate(set, function (it) {\n add(result, it);\n });\n return result;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/set-clone.js\n// module id = 173\n// module chunks = 0","'use strict';\nvar PROPER_FUNCTION_NAME = require('../internals/function-name').PROPER;\nvar fails = require('../internals/fails');\nvar whitespaces = require('../internals/whitespaces');\n\nvar non = '\\u200B\\u0085\\u180E';\n\n// check that a method works with the correct list\n// of whitespaces and has a correct name\nmodule.exports = function (METHOD_NAME) {\n return fails(function () {\n return !!whitespaces[METHOD_NAME]()\n || non[METHOD_NAME]() !== non\n || (PROPER_FUNCTION_NAME && whitespaces[METHOD_NAME].name !== METHOD_NAME);\n });\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/string-trim-forced.js\n// module id = 174\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar fails = require('../internals/fails');\nvar V8 = require('../internals/environment-v8-version');\nvar ENVIRONMENT = require('../internals/environment');\n\nvar structuredClone = globalThis.structuredClone;\n\nmodule.exports = !!structuredClone && !fails(function () {\n // prevent V8 ArrayBufferDetaching protector cell invalidation and performance degradation\n // https://github.com/zloirock/core-js/issues/679\n if ((ENVIRONMENT === 'DENO' && V8 > 92) || (ENVIRONMENT === 'NODE' && V8 > 94) || (ENVIRONMENT === 'BROWSER' && V8 > 97)) return false;\n var buffer = new ArrayBuffer(8);\n var clone = structuredClone(buffer, { transfer: [buffer] });\n return buffer.byteLength !== 0 || clone.byteLength !== 8;\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/structured-clone-proper-transfer.js\n// module id = 175\n// module chunks = 0","'use strict';\nvar toPrimitive = require('../internals/to-primitive');\n\nvar $TypeError = TypeError;\n\n// `ToBigInt` abstract operation\n// https://tc39.es/ecma262/#sec-tobigint\nmodule.exports = function (argument) {\n var prim = toPrimitive(argument, 'number');\n if (typeof prim == 'number') throw new $TypeError(\"Can't convert number to bigint\");\n // eslint-disable-next-line es/no-bigint -- safe\n return BigInt(prim);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/to-big-int.js\n// module id = 176\n// module chunks = 0","'use strict';\nvar toIntegerOrInfinity = require('../internals/to-integer-or-infinity');\n\nvar $RangeError = RangeError;\n\nmodule.exports = function (it) {\n var result = toIntegerOrInfinity(it);\n if (result < 0) throw new $RangeError(\"The argument can't be less than 0\");\n return result;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/to-positive-integer.js\n// module id = 177\n// module chunks = 0","'use strict';\nvar wellKnownSymbol = require('../internals/well-known-symbol');\n\nvar TO_STRING_TAG = wellKnownSymbol('toStringTag');\nvar test = {};\n\ntest[TO_STRING_TAG] = 'z';\n\nmodule.exports = String(test) === '[object z]';\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/to-string-tag-support.js\n// module id = 178\n// module chunks = 0","'use strict';\n/* eslint-disable no-new, sonarjs/inconsistent-function-call -- required for testing */\nvar globalThis = require('../internals/global-this');\nvar fails = require('../internals/fails');\nvar checkCorrectnessOfIteration = require('../internals/check-correctness-of-iteration');\nvar NATIVE_ARRAY_BUFFER_VIEWS = require('../internals/array-buffer-view-core').NATIVE_ARRAY_BUFFER_VIEWS;\n\nvar ArrayBuffer = globalThis.ArrayBuffer;\nvar Int8Array = globalThis.Int8Array;\n\nmodule.exports = !NATIVE_ARRAY_BUFFER_VIEWS || !fails(function () {\n Int8Array(1);\n}) || !fails(function () {\n new Int8Array(-1);\n}) || !checkCorrectnessOfIteration(function (iterable) {\n new Int8Array();\n new Int8Array(null);\n new Int8Array(1.5);\n new Int8Array(iterable);\n}, true) || fails(function () {\n // Safari (11+) bug - a reason why even Safari 13 should load a typed array polyfill\n return new Int8Array(new ArrayBuffer(2), 1, undefined).length !== 1;\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/typed-array-constructors-require-wrappers.js\n// module id = 179\n// module chunks = 0","'use strict';\nvar $ = require('../internals/export');\nvar exec = require('../internals/regexp-exec');\n\n// `RegExp.prototype.exec` method\n// https://tc39.es/ecma262/#sec-regexp.prototype.exec\n$({ target: 'RegExp', proto: true, forced: /./.exec !== exec }, {\n exec: exec\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es.regexp.exec.js\n// module id = 180\n// module chunks = 0","'use strict';\nvar isPossiblePrototype = require('../internals/is-possible-prototype');\n\nvar $String = String;\nvar $TypeError = TypeError;\n\nmodule.exports = function (argument) {\n if (isPossiblePrototype(argument)) return argument;\n throw new $TypeError(\"Can't set \" + $String(argument) + ' as a prototype');\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/a-possible-prototype.js\n// module id = 181\n// module chunks = 0","'use strict';\nvar getBuiltIn = require('../internals/get-built-in');\nvar call = require('../internals/function-call');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar bind = require('../internals/function-bind-context');\nvar anObject = require('../internals/an-object');\nvar aCallable = require('../internals/a-callable');\nvar isNullOrUndefined = require('../internals/is-null-or-undefined');\nvar getMethod = require('../internals/get-method');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\n\nvar ASYNC_DISPOSE = wellKnownSymbol('asyncDispose');\nvar DISPOSE = wellKnownSymbol('dispose');\n\nvar push = uncurryThis([].push);\n\n// `GetDisposeMethod` abstract operation\n// https://tc39.es/proposal-explicit-resource-management/#sec-getdisposemethod\nvar getDisposeMethod = function (V, hint) {\n if (hint === 'async-dispose') {\n var method = getMethod(V, ASYNC_DISPOSE);\n if (method !== undefined) return method;\n method = getMethod(V, DISPOSE);\n if (method === undefined) return method;\n return function () {\n var O = this;\n var Promise = getBuiltIn('Promise');\n return new Promise(function (resolve) {\n call(method, O);\n resolve(undefined);\n });\n };\n } return getMethod(V, DISPOSE);\n};\n\n// `CreateDisposableResource` abstract operation\n// https://tc39.es/proposal-explicit-resource-management/#sec-createdisposableresource\nvar createDisposableResource = function (V, hint, method) {\n if (arguments.length < 3 && !isNullOrUndefined(V)) {\n method = aCallable(getDisposeMethod(anObject(V), hint));\n }\n\n return method === undefined ? function () {\n return undefined;\n } : bind(method, V);\n};\n\n// `AddDisposableResource` abstract operation\n// https://tc39.es/proposal-explicit-resource-management/#sec-adddisposableresource\nmodule.exports = function (disposable, V, hint, method) {\n var resource;\n if (arguments.length < 4) {\n // When `V`` is either `null` or `undefined` and hint is `async-dispose`,\n // we record that the resource was evaluated to ensure we will still perform an `Await` when resources are later disposed.\n if (isNullOrUndefined(V) && hint === 'sync-dispose') return;\n resource = createDisposableResource(V, hint);\n } else {\n resource = createDisposableResource(undefined, hint, method);\n }\n\n push(disposable.stack, resource);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/add-disposable-resource.js\n// module id = 182\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar uncurryThisAccessor = require('../internals/function-uncurry-this-accessor');\nvar classof = require('../internals/classof-raw');\n\nvar ArrayBuffer = globalThis.ArrayBuffer;\nvar TypeError = globalThis.TypeError;\n\n// Includes\n// - Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).\n// - If IsSharedArrayBuffer(O) is true, throw a TypeError exception.\nmodule.exports = ArrayBuffer && uncurryThisAccessor(ArrayBuffer.prototype, 'byteLength', 'get') || function (O) {\n if (classof(O) !== 'ArrayBuffer') throw new TypeError('ArrayBuffer expected');\n return O.byteLength;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-buffer-byte-length.js\n// module id = 183\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar NATIVE_ARRAY_BUFFER = require('../internals/array-buffer-basic-detection');\nvar arrayBufferByteLength = require('../internals/array-buffer-byte-length');\n\nvar DataView = globalThis.DataView;\n\nmodule.exports = function (O) {\n if (!NATIVE_ARRAY_BUFFER || arrayBufferByteLength(O) !== 0) return false;\n try {\n // eslint-disable-next-line no-new -- thrower\n new DataView(O);\n return false;\n } catch (error) {\n return true;\n }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-buffer-is-detached.js\n// module id = 184\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar uncurryThisAccessor = require('../internals/function-uncurry-this-accessor');\nvar toIndex = require('../internals/to-index');\nvar notDetached = require('../internals/array-buffer-not-detached');\nvar arrayBufferByteLength = require('../internals/array-buffer-byte-length');\nvar detachTransferable = require('../internals/detach-transferable');\nvar PROPER_STRUCTURED_CLONE_TRANSFER = require('../internals/structured-clone-proper-transfer');\n\nvar structuredClone = globalThis.structuredClone;\nvar ArrayBuffer = globalThis.ArrayBuffer;\nvar DataView = globalThis.DataView;\nvar min = Math.min;\nvar ArrayBufferPrototype = ArrayBuffer.prototype;\nvar DataViewPrototype = DataView.prototype;\nvar slice = uncurryThis(ArrayBufferPrototype.slice);\nvar isResizable = uncurryThisAccessor(ArrayBufferPrototype, 'resizable', 'get');\nvar maxByteLength = uncurryThisAccessor(ArrayBufferPrototype, 'maxByteLength', 'get');\nvar getInt8 = uncurryThis(DataViewPrototype.getInt8);\nvar setInt8 = uncurryThis(DataViewPrototype.setInt8);\n\nmodule.exports = (PROPER_STRUCTURED_CLONE_TRANSFER || detachTransferable) && function (arrayBuffer, newLength, preserveResizability) {\n var byteLength = arrayBufferByteLength(arrayBuffer);\n var newByteLength = newLength === undefined ? byteLength : toIndex(newLength);\n var fixedLength = !isResizable || !isResizable(arrayBuffer);\n var newBuffer;\n notDetached(arrayBuffer);\n if (PROPER_STRUCTURED_CLONE_TRANSFER) {\n arrayBuffer = structuredClone(arrayBuffer, { transfer: [arrayBuffer] });\n if (byteLength === newByteLength && (preserveResizability || fixedLength)) return arrayBuffer;\n }\n if (byteLength >= newByteLength && (!preserveResizability || fixedLength)) {\n newBuffer = slice(arrayBuffer, 0, newByteLength);\n } else {\n var options = preserveResizability && !fixedLength && maxByteLength ? { maxByteLength: maxByteLength(arrayBuffer) } : undefined;\n newBuffer = new ArrayBuffer(newByteLength, options);\n var a = new DataView(arrayBuffer);\n var b = new DataView(newBuffer);\n var copyLength = min(newByteLength, byteLength);\n for (var i = 0; i < copyLength; i++) setInt8(b, i, getInt8(a, i));\n }\n if (!PROPER_STRUCTURED_CLONE_TRANSFER) detachTransferable(arrayBuffer);\n return newBuffer;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-buffer-transfer.js\n// module id = 185\n// module chunks = 0","'use strict';\nvar toObject = require('../internals/to-object');\nvar toAbsoluteIndex = require('../internals/to-absolute-index');\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\nvar deletePropertyOrThrow = require('../internals/delete-property-or-throw');\n\nvar min = Math.min;\n\n// `Array.prototype.copyWithin` method implementation\n// https://tc39.es/ecma262/#sec-array.prototype.copywithin\n// eslint-disable-next-line es/no-array-prototype-copywithin -- safe\nmodule.exports = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) {\n var O = toObject(this);\n var len = lengthOfArrayLike(O);\n var to = toAbsoluteIndex(target, len);\n var from = toAbsoluteIndex(start, len);\n var end = arguments.length > 2 ? arguments[2] : undefined;\n var count = min((end === undefined ? len : toAbsoluteIndex(end, len)) - from, len - to);\n var inc = 1;\n if (from < to && to < from + count) {\n inc = -1;\n from += count - 1;\n to += count - 1;\n }\n while (count-- > 0) {\n if (from in O) O[to] = O[from];\n else deletePropertyOrThrow(O, to);\n to += inc;\n from += inc;\n } return O;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-copy-within.js\n// module id = 186\n// module chunks = 0","'use strict';\nvar $forEach = require('../internals/array-iteration').forEach;\nvar arrayMethodIsStrict = require('../internals/array-method-is-strict');\n\nvar STRICT_METHOD = arrayMethodIsStrict('forEach');\n\n// `Array.prototype.forEach` method implementation\n// https://tc39.es/ecma262/#sec-array.prototype.foreach\nmodule.exports = !STRICT_METHOD ? function forEach(callbackfn /* , thisArg */) {\n return $forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n// eslint-disable-next-line es/no-array-prototype-foreach -- safe\n} : [].forEach;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-for-each.js\n// module id = 187\n// module chunks = 0","'use strict';\nvar bind = require('../internals/function-bind-context');\nvar call = require('../internals/function-call');\nvar toObject = require('../internals/to-object');\nvar callWithSafeIterationClosing = require('../internals/call-with-safe-iteration-closing');\nvar isArrayIteratorMethod = require('../internals/is-array-iterator-method');\nvar isConstructor = require('../internals/is-constructor');\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\nvar createProperty = require('../internals/create-property');\nvar getIterator = require('../internals/get-iterator');\nvar getIteratorMethod = require('../internals/get-iterator-method');\n\nvar $Array = Array;\n\n// `Array.from` method implementation\n// https://tc39.es/ecma262/#sec-array.from\nmodule.exports = function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {\n var O = toObject(arrayLike);\n var IS_CONSTRUCTOR = isConstructor(this);\n var argumentsLength = arguments.length;\n var mapfn = argumentsLength > 1 ? arguments[1] : undefined;\n var mapping = mapfn !== undefined;\n if (mapping) mapfn = bind(mapfn, argumentsLength > 2 ? arguments[2] : undefined);\n var iteratorMethod = getIteratorMethod(O);\n var index = 0;\n var length, result, step, iterator, next, value;\n // if the target is not iterable or it's an array with the default iterator - use a simple case\n if (iteratorMethod && !(this === $Array && isArrayIteratorMethod(iteratorMethod))) {\n result = IS_CONSTRUCTOR ? new this() : [];\n iterator = getIterator(O, iteratorMethod);\n next = iterator.next;\n for (;!(step = call(next, iterator)).done; index++) {\n value = mapping ? callWithSafeIterationClosing(iterator, mapfn, [step.value, index], true) : step.value;\n createProperty(result, index, value);\n }\n } else {\n length = lengthOfArrayLike(O);\n result = IS_CONSTRUCTOR ? new this(length) : $Array(length);\n for (;length > index; index++) {\n value = mapping ? mapfn(O[index], index) : O[index];\n createProperty(result, index, value);\n }\n }\n result.length = index;\n return result;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-from.js\n// module id = 188\n// module chunks = 0","'use strict';\n/* eslint-disable es/no-array-prototype-lastindexof -- safe */\nvar apply = require('../internals/function-apply');\nvar toIndexedObject = require('../internals/to-indexed-object');\nvar toIntegerOrInfinity = require('../internals/to-integer-or-infinity');\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\nvar arrayMethodIsStrict = require('../internals/array-method-is-strict');\n\nvar min = Math.min;\nvar $lastIndexOf = [].lastIndexOf;\nvar NEGATIVE_ZERO = !!$lastIndexOf && 1 / [1].lastIndexOf(1, -0) < 0;\nvar STRICT_METHOD = arrayMethodIsStrict('lastIndexOf');\nvar FORCED = NEGATIVE_ZERO || !STRICT_METHOD;\n\n// `Array.prototype.lastIndexOf` method implementation\n// https://tc39.es/ecma262/#sec-array.prototype.lastindexof\nmodule.exports = FORCED ? function lastIndexOf(searchElement /* , fromIndex = @[*-1] */) {\n // convert -0 to +0\n if (NEGATIVE_ZERO) return apply($lastIndexOf, this, arguments) || 0;\n var O = toIndexedObject(this);\n var length = lengthOfArrayLike(O);\n if (length === 0) return -1;\n var index = length - 1;\n if (arguments.length > 1) index = min(index, toIntegerOrInfinity(arguments[1]));\n if (index < 0) index = length + index;\n for (;index >= 0; index--) if (index in O && O[index] === searchElement) return index || 0;\n return -1;\n} : $lastIndexOf;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-last-index-of.js\n// module id = 189\n// module chunks = 0","'use strict';\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\n\n// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toReversed\n// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toReversed\nmodule.exports = function (O, C) {\n var len = lengthOfArrayLike(O);\n var A = new C(len);\n var k = 0;\n for (; k < len; k++) A[k] = O[len - k - 1];\n return A;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-to-reversed.js\n// module id = 190\n// module chunks = 0","'use strict';\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\nvar toIntegerOrInfinity = require('../internals/to-integer-or-infinity');\n\nvar $RangeError = RangeError;\n\n// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.with\n// https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.with\nmodule.exports = function (O, C, index, value) {\n var len = lengthOfArrayLike(O);\n var relativeIndex = toIntegerOrInfinity(index);\n var actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex;\n if (actualIndex >= len || actualIndex < 0) throw new $RangeError('Incorrect index');\n var A = new C(len);\n var k = 0;\n for (; k < len; k++) A[k] = k === actualIndex ? value : O[k];\n return A;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/array-with.js\n// module id = 191\n// module chunks = 0","'use strict';\nvar call = require('../internals/function-call');\nvar anObject = require('../internals/an-object');\nvar create = require('../internals/object-create');\nvar getMethod = require('../internals/get-method');\nvar defineBuiltIns = require('../internals/define-built-ins');\nvar InternalStateModule = require('../internals/internal-state');\nvar iteratorClose = require('../internals/iterator-close');\nvar getBuiltIn = require('../internals/get-built-in');\nvar AsyncIteratorPrototype = require('../internals/async-iterator-prototype');\nvar createIterResultObject = require('../internals/create-iter-result-object');\n\nvar Promise = getBuiltIn('Promise');\n\nvar ASYNC_FROM_SYNC_ITERATOR = 'AsyncFromSyncIterator';\nvar setInternalState = InternalStateModule.set;\nvar getInternalState = InternalStateModule.getterFor(ASYNC_FROM_SYNC_ITERATOR);\n\nvar asyncFromSyncIteratorContinuation = function (result, resolve, reject, syncIterator, closeOnRejection) {\n var done = result.done;\n Promise.resolve(result.value).then(function (value) {\n resolve(createIterResultObject(value, done));\n }, function (error) {\n if (!done && closeOnRejection) {\n try {\n iteratorClose(syncIterator, 'throw', error);\n } catch (error2) {\n error = error2;\n }\n }\n\n reject(error);\n });\n};\n\nvar AsyncFromSyncIterator = function AsyncIterator(iteratorRecord) {\n iteratorRecord.type = ASYNC_FROM_SYNC_ITERATOR;\n setInternalState(this, iteratorRecord);\n};\n\nAsyncFromSyncIterator.prototype = defineBuiltIns(create(AsyncIteratorPrototype), {\n next: function next() {\n var state = getInternalState(this);\n return new Promise(function (resolve, reject) {\n var result = anObject(call(state.next, state.iterator));\n asyncFromSyncIteratorContinuation(result, resolve, reject, state.iterator, true);\n });\n },\n 'return': function () {\n var iterator = getInternalState(this).iterator;\n return new Promise(function (resolve, reject) {\n var $return = getMethod(iterator, 'return');\n if ($return === undefined) return resolve(createIterResultObject(undefined, true));\n var result = anObject(call($return, iterator));\n asyncFromSyncIteratorContinuation(result, resolve, reject, iterator);\n });\n }\n});\n\nmodule.exports = AsyncFromSyncIterator;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/async-from-sync-iterator.js\n// module id = 192\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar shared = require('../internals/shared-store');\nvar isCallable = require('../internals/is-callable');\nvar create = require('../internals/object-create');\nvar getPrototypeOf = require('../internals/object-get-prototype-of');\nvar defineBuiltIn = require('../internals/define-built-in');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\nvar IS_PURE = require('../internals/is-pure');\n\nvar USE_FUNCTION_CONSTRUCTOR = 'USE_FUNCTION_CONSTRUCTOR';\nvar ASYNC_ITERATOR = wellKnownSymbol('asyncIterator');\nvar AsyncIterator = globalThis.AsyncIterator;\nvar PassedAsyncIteratorPrototype = shared.AsyncIteratorPrototype;\nvar AsyncIteratorPrototype, prototype;\n\nif (PassedAsyncIteratorPrototype) {\n AsyncIteratorPrototype = PassedAsyncIteratorPrototype;\n} else if (isCallable(AsyncIterator)) {\n AsyncIteratorPrototype = AsyncIterator.prototype;\n} else if (shared[USE_FUNCTION_CONSTRUCTOR] || globalThis[USE_FUNCTION_CONSTRUCTOR]) {\n try {\n // eslint-disable-next-line no-new-func -- we have no alternatives without usage of modern syntax\n prototype = getPrototypeOf(getPrototypeOf(getPrototypeOf(Function('return async function*(){}()')())));\n if (getPrototypeOf(prototype) === Object.prototype) AsyncIteratorPrototype = prototype;\n } catch (error) { /* empty */ }\n}\n\nif (!AsyncIteratorPrototype) AsyncIteratorPrototype = {};\nelse if (IS_PURE) AsyncIteratorPrototype = create(AsyncIteratorPrototype);\n\nif (!isCallable(AsyncIteratorPrototype[ASYNC_ITERATOR])) {\n defineBuiltIn(AsyncIteratorPrototype, ASYNC_ITERATOR, function () {\n return this;\n });\n}\n\nmodule.exports = AsyncIteratorPrototype;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/async-iterator-prototype.js\n// module id = 193\n// module chunks = 0","'use strict';\nvar commonAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\nvar base64Alphabet = commonAlphabet + '+/';\nvar base64UrlAlphabet = commonAlphabet + '-_';\n\nvar inverse = function (characters) {\n // TODO: use `Object.create(null)` in `core-js@4`\n var result = {};\n var index = 0;\n for (; index < 64; index++) result[characters.charAt(index)] = index;\n return result;\n};\n\nmodule.exports = {\n i2c: base64Alphabet,\n c2i: inverse(base64Alphabet),\n i2cUrl: base64UrlAlphabet,\n c2iUrl: inverse(base64UrlAlphabet)\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/base64-map.js\n// module id = 194\n// module chunks = 0","'use strict';\nvar create = require('../internals/object-create');\nvar defineBuiltInAccessor = require('../internals/define-built-in-accessor');\nvar defineBuiltIns = require('../internals/define-built-ins');\nvar bind = require('../internals/function-bind-context');\nvar anInstance = require('../internals/an-instance');\nvar isNullOrUndefined = require('../internals/is-null-or-undefined');\nvar iterate = require('../internals/iterate');\nvar defineIterator = require('../internals/iterator-define');\nvar createIterResultObject = require('../internals/create-iter-result-object');\nvar setSpecies = require('../internals/set-species');\nvar DESCRIPTORS = require('../internals/descriptors');\nvar fastKey = require('../internals/internal-metadata').fastKey;\nvar InternalStateModule = require('../internals/internal-state');\n\nvar setInternalState = InternalStateModule.set;\nvar internalStateGetterFor = InternalStateModule.getterFor;\n\nmodule.exports = {\n getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {\n var Constructor = wrapper(function (that, iterable) {\n anInstance(that, Prototype);\n setInternalState(that, {\n type: CONSTRUCTOR_NAME,\n index: create(null),\n first: null,\n last: null,\n size: 0\n });\n if (!DESCRIPTORS) that.size = 0;\n if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });\n });\n\n var Prototype = Constructor.prototype;\n\n var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);\n\n var define = function (that, key, value) {\n var state = getInternalState(that);\n var entry = getEntry(that, key);\n var previous, index;\n // change existing entry\n if (entry) {\n entry.value = value;\n // create new entry\n } else {\n state.last = entry = {\n index: index = fastKey(key, true),\n key: key,\n value: value,\n previous: previous = state.last,\n next: null,\n removed: false\n };\n if (!state.first) state.first = entry;\n if (previous) previous.next = entry;\n if (DESCRIPTORS) state.size++;\n else that.size++;\n // add to index\n if (index !== 'F') state.index[index] = entry;\n } return that;\n };\n\n var getEntry = function (that, key) {\n var state = getInternalState(that);\n // fast case\n var index = fastKey(key);\n var entry;\n if (index !== 'F') return state.index[index];\n // frozen object case\n for (entry = state.first; entry; entry = entry.next) {\n if (entry.key === key) return entry;\n }\n };\n\n defineBuiltIns(Prototype, {\n // `{ Map, Set }.prototype.clear()` methods\n // https://tc39.es/ecma262/#sec-map.prototype.clear\n // https://tc39.es/ecma262/#sec-set.prototype.clear\n clear: function clear() {\n var that = this;\n var state = getInternalState(that);\n var entry = state.first;\n while (entry) {\n entry.removed = true;\n if (entry.previous) entry.previous = entry.previous.next = null;\n entry = entry.next;\n }\n state.first = state.last = null;\n state.index = create(null);\n if (DESCRIPTORS) state.size = 0;\n else that.size = 0;\n },\n // `{ Map, Set }.prototype.delete(key)` methods\n // https://tc39.es/ecma262/#sec-map.prototype.delete\n // https://tc39.es/ecma262/#sec-set.prototype.delete\n 'delete': function (key) {\n var that = this;\n var state = getInternalState(that);\n var entry = getEntry(that, key);\n if (entry) {\n var next = entry.next;\n var prev = entry.previous;\n delete state.index[entry.index];\n entry.removed = true;\n if (prev) prev.next = next;\n if (next) next.previous = prev;\n if (state.first === entry) state.first = next;\n if (state.last === entry) state.last = prev;\n if (DESCRIPTORS) state.size--;\n else that.size--;\n } return !!entry;\n },\n // `{ Map, Set }.prototype.forEach(callbackfn, thisArg = undefined)` methods\n // https://tc39.es/ecma262/#sec-map.prototype.foreach\n // https://tc39.es/ecma262/#sec-set.prototype.foreach\n forEach: function forEach(callbackfn /* , that = undefined */) {\n var state = getInternalState(this);\n var boundFunction = bind(callbackfn, arguments.length > 1 ? arguments[1] : undefined);\n var entry;\n while (entry = entry ? entry.next : state.first) {\n boundFunction(entry.value, entry.key, this);\n // revert to the last existing entry\n while (entry && entry.removed) entry = entry.previous;\n }\n },\n // `{ Map, Set}.prototype.has(key)` methods\n // https://tc39.es/ecma262/#sec-map.prototype.has\n // https://tc39.es/ecma262/#sec-set.prototype.has\n has: function has(key) {\n return !!getEntry(this, key);\n }\n });\n\n defineBuiltIns(Prototype, IS_MAP ? {\n // `Map.prototype.get(key)` method\n // https://tc39.es/ecma262/#sec-map.prototype.get\n get: function get(key) {\n var entry = getEntry(this, key);\n return entry && entry.value;\n },\n // `Map.prototype.set(key, value)` method\n // https://tc39.es/ecma262/#sec-map.prototype.set\n set: function set(key, value) {\n return define(this, key === 0 ? 0 : key, value);\n }\n } : {\n // `Set.prototype.add(value)` method\n // https://tc39.es/ecma262/#sec-set.prototype.add\n add: function add(value) {\n return define(this, value = value === 0 ? 0 : value, value);\n }\n });\n if (DESCRIPTORS) defineBuiltInAccessor(Prototype, 'size', {\n configurable: true,\n get: function () {\n return getInternalState(this).size;\n }\n });\n return Constructor;\n },\n setStrong: function (Constructor, CONSTRUCTOR_NAME, IS_MAP) {\n var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator';\n var getInternalCollectionState = internalStateGetterFor(CONSTRUCTOR_NAME);\n var getInternalIteratorState = internalStateGetterFor(ITERATOR_NAME);\n // `{ Map, Set }.prototype.{ keys, values, entries, @@iterator }()` methods\n // https://tc39.es/ecma262/#sec-map.prototype.entries\n // https://tc39.es/ecma262/#sec-map.prototype.keys\n // https://tc39.es/ecma262/#sec-map.prototype.values\n // https://tc39.es/ecma262/#sec-map.prototype-@@iterator\n // https://tc39.es/ecma262/#sec-set.prototype.entries\n // https://tc39.es/ecma262/#sec-set.prototype.keys\n // https://tc39.es/ecma262/#sec-set.prototype.values\n // https://tc39.es/ecma262/#sec-set.prototype-@@iterator\n defineIterator(Constructor, CONSTRUCTOR_NAME, function (iterated, kind) {\n setInternalState(this, {\n type: ITERATOR_NAME,\n target: iterated,\n state: getInternalCollectionState(iterated),\n kind: kind,\n last: null\n });\n }, function () {\n var state = getInternalIteratorState(this);\n var kind = state.kind;\n var entry = state.last;\n // revert to the last existing entry\n while (entry && entry.removed) entry = entry.previous;\n // get next entry\n if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) {\n // or finish the iteration\n state.target = null;\n return createIterResultObject(undefined, true);\n }\n // return step by kind\n if (kind === 'keys') return createIterResultObject(entry.key, false);\n if (kind === 'values') return createIterResultObject(entry.value, false);\n return createIterResultObject([entry.key, entry.value], false);\n }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);\n\n // `{ Map, Set }.prototype[@@species]` accessors\n // https://tc39.es/ecma262/#sec-get-map-@@species\n // https://tc39.es/ecma262/#sec-get-set-@@species\n setSpecies(CONSTRUCTOR_NAME);\n }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/collection-strong.js\n// module id = 195\n// module chunks = 0","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar defineBuiltIns = require('../internals/define-built-ins');\nvar getWeakData = require('../internals/internal-metadata').getWeakData;\nvar anInstance = require('../internals/an-instance');\nvar anObject = require('../internals/an-object');\nvar isNullOrUndefined = require('../internals/is-null-or-undefined');\nvar isObject = require('../internals/is-object');\nvar iterate = require('../internals/iterate');\nvar ArrayIterationModule = require('../internals/array-iteration');\nvar hasOwn = require('../internals/has-own-property');\nvar InternalStateModule = require('../internals/internal-state');\n\nvar setInternalState = InternalStateModule.set;\nvar internalStateGetterFor = InternalStateModule.getterFor;\nvar find = ArrayIterationModule.find;\nvar findIndex = ArrayIterationModule.findIndex;\nvar splice = uncurryThis([].splice);\nvar id = 0;\n\n// fallback for uncaught frozen keys\nvar uncaughtFrozenStore = function (state) {\n return state.frozen || (state.frozen = new UncaughtFrozenStore());\n};\n\nvar UncaughtFrozenStore = function () {\n this.entries = [];\n};\n\nvar findUncaughtFrozen = function (store, key) {\n return find(store.entries, function (it) {\n return it[0] === key;\n });\n};\n\nUncaughtFrozenStore.prototype = {\n get: function (key) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) return entry[1];\n },\n has: function (key) {\n return !!findUncaughtFrozen(this, key);\n },\n set: function (key, value) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) entry[1] = value;\n else this.entries.push([key, value]);\n },\n 'delete': function (key) {\n var index = findIndex(this.entries, function (it) {\n return it[0] === key;\n });\n if (~index) splice(this.entries, index, 1);\n return !!~index;\n }\n};\n\nmodule.exports = {\n getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {\n var Constructor = wrapper(function (that, iterable) {\n anInstance(that, Prototype);\n setInternalState(that, {\n type: CONSTRUCTOR_NAME,\n id: id++,\n frozen: null\n });\n if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });\n });\n\n var Prototype = Constructor.prototype;\n\n var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);\n\n var define = function (that, key, value) {\n var state = getInternalState(that);\n var data = getWeakData(anObject(key), true);\n if (data === true) uncaughtFrozenStore(state).set(key, value);\n else data[state.id] = value;\n return that;\n };\n\n defineBuiltIns(Prototype, {\n // `{ WeakMap, WeakSet }.prototype.delete(key)` methods\n // https://tc39.es/ecma262/#sec-weakmap.prototype.delete\n // https://tc39.es/ecma262/#sec-weakset.prototype.delete\n 'delete': function (key) {\n var state = getInternalState(this);\n if (!isObject(key)) return false;\n var data = getWeakData(key);\n if (data === true) return uncaughtFrozenStore(state)['delete'](key);\n return data && hasOwn(data, state.id) && delete data[state.id];\n },\n // `{ WeakMap, WeakSet }.prototype.has(key)` methods\n // https://tc39.es/ecma262/#sec-weakmap.prototype.has\n // https://tc39.es/ecma262/#sec-weakset.prototype.has\n has: function has(key) {\n var state = getInternalState(this);\n if (!isObject(key)) return false;\n var data = getWeakData(key);\n if (data === true) return uncaughtFrozenStore(state).has(key);\n return data && hasOwn(data, state.id);\n }\n });\n\n defineBuiltIns(Prototype, IS_MAP ? {\n // `WeakMap.prototype.get(key)` method\n // https://tc39.es/ecma262/#sec-weakmap.prototype.get\n get: function get(key) {\n var state = getInternalState(this);\n if (isObject(key)) {\n var data = getWeakData(key);\n if (data === true) return uncaughtFrozenStore(state).get(key);\n if (data) return data[state.id];\n }\n },\n // `WeakMap.prototype.set(key, value)` method\n // https://tc39.es/ecma262/#sec-weakmap.prototype.set\n set: function set(key, value) {\n return define(this, key, value);\n }\n } : {\n // `WeakSet.prototype.add(value)` method\n // https://tc39.es/ecma262/#sec-weakset.prototype.add\n add: function add(value) {\n return define(this, value, true);\n }\n });\n\n return Constructor;\n }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/collection-weak.js\n// module id = 196\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar getBuiltInNodeModule = require('../internals/get-built-in-node-module');\nvar PROPER_STRUCTURED_CLONE_TRANSFER = require('../internals/structured-clone-proper-transfer');\n\nvar structuredClone = globalThis.structuredClone;\nvar $ArrayBuffer = globalThis.ArrayBuffer;\nvar $MessageChannel = globalThis.MessageChannel;\nvar detach = false;\nvar WorkerThreads, channel, buffer, $detach;\n\nif (PROPER_STRUCTURED_CLONE_TRANSFER) {\n detach = function (transferable) {\n structuredClone(transferable, { transfer: [transferable] });\n };\n} else if ($ArrayBuffer) try {\n if (!$MessageChannel) {\n WorkerThreads = getBuiltInNodeModule('worker_threads');\n if (WorkerThreads) $MessageChannel = WorkerThreads.MessageChannel;\n }\n\n if ($MessageChannel) {\n channel = new $MessageChannel();\n buffer = new $ArrayBuffer(2);\n\n $detach = function (transferable) {\n channel.port1.postMessage(null, [transferable]);\n };\n\n if (buffer.byteLength === 2) {\n $detach(buffer);\n if (buffer.byteLength === 0) detach = $detach;\n }\n }\n} catch (error) { /* empty */ }\n\nmodule.exports = detach;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/detach-transferable.js\n// module id = 197\n// module chunks = 0","'use strict';\nmodule.exports = {\n IndexSizeError: { s: 'INDEX_SIZE_ERR', c: 1, m: 1 },\n DOMStringSizeError: { s: 'DOMSTRING_SIZE_ERR', c: 2, m: 0 },\n HierarchyRequestError: { s: 'HIERARCHY_REQUEST_ERR', c: 3, m: 1 },\n WrongDocumentError: { s: 'WRONG_DOCUMENT_ERR', c: 4, m: 1 },\n InvalidCharacterError: { s: 'INVALID_CHARACTER_ERR', c: 5, m: 1 },\n NoDataAllowedError: { s: 'NO_DATA_ALLOWED_ERR', c: 6, m: 0 },\n NoModificationAllowedError: { s: 'NO_MODIFICATION_ALLOWED_ERR', c: 7, m: 1 },\n NotFoundError: { s: 'NOT_FOUND_ERR', c: 8, m: 1 },\n NotSupportedError: { s: 'NOT_SUPPORTED_ERR', c: 9, m: 1 },\n InUseAttributeError: { s: 'INUSE_ATTRIBUTE_ERR', c: 10, m: 1 },\n InvalidStateError: { s: 'INVALID_STATE_ERR', c: 11, m: 1 },\n SyntaxError: { s: 'SYNTAX_ERR', c: 12, m: 1 },\n InvalidModificationError: { s: 'INVALID_MODIFICATION_ERR', c: 13, m: 1 },\n NamespaceError: { s: 'NAMESPACE_ERR', c: 14, m: 1 },\n InvalidAccessError: { s: 'INVALID_ACCESS_ERR', c: 15, m: 1 },\n ValidationError: { s: 'VALIDATION_ERR', c: 16, m: 0 },\n TypeMismatchError: { s: 'TYPE_MISMATCH_ERR', c: 17, m: 1 },\n SecurityError: { s: 'SECURITY_ERR', c: 18, m: 1 },\n NetworkError: { s: 'NETWORK_ERR', c: 19, m: 1 },\n AbortError: { s: 'ABORT_ERR', c: 20, m: 1 },\n URLMismatchError: { s: 'URL_MISMATCH_ERR', c: 21, m: 1 },\n QuotaExceededError: { s: 'QUOTA_EXCEEDED_ERR', c: 22, m: 1 },\n TimeoutError: { s: 'TIMEOUT_ERR', c: 23, m: 1 },\n InvalidNodeTypeError: { s: 'INVALID_NODE_TYPE_ERR', c: 24, m: 1 },\n DataCloneError: { s: 'DATA_CLONE_ERR', c: 25, m: 1 }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/dom-exception-constants.js\n// module id = 198\n// module chunks = 0","'use strict';\n// iterable DOM collections\n// flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods\nmodule.exports = {\n CSSRuleList: 0,\n CSSStyleDeclaration: 0,\n CSSValueList: 0,\n ClientRectList: 0,\n DOMRectList: 0,\n DOMStringList: 0,\n DOMTokenList: 1,\n DataTransferItemList: 0,\n FileList: 0,\n HTMLAllCollection: 0,\n HTMLCollection: 0,\n HTMLFormElement: 0,\n HTMLSelectElement: 0,\n MediaList: 0,\n MimeTypeArray: 0,\n NamedNodeMap: 0,\n NodeList: 1,\n PaintRequestList: 0,\n Plugin: 0,\n PluginArray: 0,\n SVGLengthList: 0,\n SVGNumberList: 0,\n SVGPathSegList: 0,\n SVGPointList: 0,\n SVGStringList: 0,\n SVGTransformList: 0,\n SourceBufferList: 0,\n StyleSheetList: 0,\n TextTrackCueList: 0,\n TextTrackList: 0,\n TouchList: 0\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/dom-iterables.js\n// module id = 199\n// module chunks = 0","'use strict';\n// in old WebKit versions, `element.classList` is not an instance of global `DOMTokenList`\nvar documentCreateElement = require('../internals/document-create-element');\n\nvar classList = documentCreateElement('span').classList;\nvar DOMTokenListPrototype = classList && classList.constructor && classList.constructor.prototype;\n\nmodule.exports = DOMTokenListPrototype === Object.prototype ? undefined : DOMTokenListPrototype;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/dom-token-list-prototype.js\n// module id = 200\n// module chunks = 0","'use strict';\nvar userAgent = require('../internals/environment-user-agent');\n\nvar firefox = userAgent.match(/firefox\\/(\\d+)/i);\n\nmodule.exports = !!firefox && +firefox[1];\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/environment-ff-version.js\n// module id = 201\n// module chunks = 0","'use strict';\nvar UA = require('../internals/environment-user-agent');\n\nmodule.exports = /MSIE|Trident/.test(UA);\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/environment-is-ie-or-edge.js\n// module id = 202\n// module chunks = 0","'use strict';\nvar userAgent = require('../internals/environment-user-agent');\n\n// eslint-disable-next-line redos/no-vulnerable -- safe\nmodule.exports = /(?:ipad|iphone|ipod).*applewebkit/i.test(userAgent);\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/environment-is-ios.js\n// module id = 203\n// module chunks = 0","'use strict';\nvar fails = require('../internals/fails');\nvar createPropertyDescriptor = require('../internals/create-property-descriptor');\n\nmodule.exports = !fails(function () {\n var error = new Error('a');\n if (!('stack' in error)) return true;\n // eslint-disable-next-line es/no-object-defineproperty -- safe\n Object.defineProperty(error, 'stack', createPropertyDescriptor(1, 7));\n return error.stack !== 7;\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/error-stack-installable.js\n// module id = 204\n// module chunks = 0","'use strict';\nvar DESCRIPTORS = require('../internals/descriptors');\nvar fails = require('../internals/fails');\nvar anObject = require('../internals/an-object');\nvar normalizeStringArgument = require('../internals/normalize-string-argument');\n\nvar nativeErrorToString = Error.prototype.toString;\n\nvar INCORRECT_TO_STRING = fails(function () {\n if (DESCRIPTORS) {\n // Chrome 32- incorrectly call accessor\n // eslint-disable-next-line es/no-object-create, es/no-object-defineproperty -- safe\n var object = Object.create(Object.defineProperty({}, 'name', { get: function () {\n return this === object;\n } }));\n if (nativeErrorToString.call(object) !== 'true') return true;\n }\n // FF10- does not properly handle non-strings\n return nativeErrorToString.call({ message: 1, name: 2 }) !== '2: 1'\n // IE8 does not properly handle defaults\n || nativeErrorToString.call({}) !== 'Error';\n});\n\nmodule.exports = INCORRECT_TO_STRING ? function toString() {\n var O = anObject(this);\n var name = normalizeStringArgument(O.name, 'Error');\n var message = normalizeStringArgument(O.message);\n return !name ? message : !message ? name : name + ': ' + message;\n} : nativeErrorToString;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/error-to-string.js\n// module id = 205\n// module chunks = 0","'use strict';\nvar isArray = require('../internals/is-array');\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\nvar doesNotExceedSafeInteger = require('../internals/does-not-exceed-safe-integer');\nvar bind = require('../internals/function-bind-context');\n\n// `FlattenIntoArray` abstract operation\n// https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray\nvar flattenIntoArray = function (target, original, source, sourceLen, start, depth, mapper, thisArg) {\n var targetIndex = start;\n var sourceIndex = 0;\n var mapFn = mapper ? bind(mapper, thisArg) : false;\n var element, elementLen;\n\n while (sourceIndex < sourceLen) {\n if (sourceIndex in source) {\n element = mapFn ? mapFn(source[sourceIndex], sourceIndex, original) : source[sourceIndex];\n\n if (depth > 0 && isArray(element)) {\n elementLen = lengthOfArrayLike(element);\n targetIndex = flattenIntoArray(target, original, element, elementLen, targetIndex, depth - 1) - 1;\n } else {\n doesNotExceedSafeInteger(targetIndex + 1);\n target[targetIndex] = element;\n }\n\n targetIndex++;\n }\n sourceIndex++;\n }\n return targetIndex;\n};\n\nmodule.exports = flattenIntoArray;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/flatten-into-array.js\n// module id = 206\n// module chunks = 0","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar aCallable = require('../internals/a-callable');\nvar isObject = require('../internals/is-object');\nvar hasOwn = require('../internals/has-own-property');\nvar arraySlice = require('../internals/array-slice');\nvar NATIVE_BIND = require('../internals/function-bind-native');\n\nvar $Function = Function;\nvar concat = uncurryThis([].concat);\nvar join = uncurryThis([].join);\nvar factories = {};\n\nvar construct = function (C, argsLength, args) {\n if (!hasOwn(factories, argsLength)) {\n var list = [];\n var i = 0;\n for (; i < argsLength; i++) list[i] = 'a[' + i + ']';\n factories[argsLength] = $Function('C,a', 'return new C(' + join(list, ',') + ')');\n } return factories[argsLength](C, args);\n};\n\n// `Function.prototype.bind` method implementation\n// https://tc39.es/ecma262/#sec-function.prototype.bind\n// eslint-disable-next-line es/no-function-prototype-bind -- detection\nmodule.exports = NATIVE_BIND ? $Function.bind : function bind(that /* , ...args */) {\n var F = aCallable(this);\n var Prototype = F.prototype;\n var partArgs = arraySlice(arguments, 1);\n var boundFunction = function bound(/* args... */) {\n var args = concat(partArgs, arraySlice(arguments));\n return this instanceof boundFunction ? construct(F, args.length, args) : F.apply(that, args);\n };\n if (isObject(Prototype)) boundFunction.prototype = Prototype;\n return boundFunction;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/function-bind.js\n// module id = 207\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar IS_NODE = require('../internals/environment-is-node');\n\nmodule.exports = function (name) {\n if (IS_NODE) {\n try {\n return globalThis.process.getBuiltinModule(name);\n } catch (error) { /* empty */ }\n try {\n // eslint-disable-next-line no-new-func -- safe\n return Function('return require(\"' + name + '\")')();\n } catch (error) { /* empty */ }\n }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/get-built-in-node-module.js\n// module id = 208\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\n\nmodule.exports = function (CONSTRUCTOR, METHOD) {\n var Constructor = globalThis[CONSTRUCTOR];\n var Prototype = Constructor && Constructor.prototype;\n return Prototype && Prototype[METHOD];\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/get-built-in-prototype-method.js\n// module id = 209\n// module chunks = 0","'use strict';\nvar call = require('../internals/function-call');\nvar anObject = require('../internals/an-object');\nvar getIteratorDirect = require('../internals/get-iterator-direct');\nvar getIteratorMethod = require('../internals/get-iterator-method');\n\nmodule.exports = function (obj, stringHandling) {\n if (!stringHandling || typeof obj !== 'string') anObject(obj);\n var method = getIteratorMethod(obj);\n return getIteratorDirect(anObject(method !== undefined ? call(method, obj) : obj));\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/get-iterator-flattenable.js\n// module id = 210\n// module chunks = 0","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar toObject = require('../internals/to-object');\n\nvar floor = Math.floor;\nvar charAt = uncurryThis(''.charAt);\nvar replace = uncurryThis(''.replace);\nvar stringSlice = uncurryThis(''.slice);\n// eslint-disable-next-line redos/no-vulnerable -- safe\nvar SUBSTITUTION_SYMBOLS = /\\$([$&'`]|\\d{1,2}|<[^>]*>)/g;\nvar SUBSTITUTION_SYMBOLS_NO_NAMED = /\\$([$&'`]|\\d{1,2})/g;\n\n// `GetSubstitution` abstract operation\n// https://tc39.es/ecma262/#sec-getsubstitution\nmodule.exports = function (matched, str, position, captures, namedCaptures, replacement) {\n var tailPos = position + matched.length;\n var m = captures.length;\n var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;\n if (namedCaptures !== undefined) {\n namedCaptures = toObject(namedCaptures);\n symbols = SUBSTITUTION_SYMBOLS;\n }\n return replace(replacement, symbols, function (match, ch) {\n var capture;\n switch (charAt(ch, 0)) {\n case '$': return '$';\n case '&': return matched;\n case '`': return stringSlice(str, 0, position);\n case \"'\": return stringSlice(str, tailPos);\n case '<':\n capture = namedCaptures[stringSlice(ch, 1, -1)];\n break;\n default: // \\d\\d?\n var n = +ch;\n if (n === 0) return match;\n if (n > m) {\n var f = floor(n / 10);\n if (f === 0) return match;\n if (f <= m) return captures[f - 1] === undefined ? charAt(ch, 1) : captures[f - 1] + charAt(ch, 1);\n return match;\n }\n capture = captures[n - 1];\n }\n return capture === undefined ? '' : capture;\n });\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/get-substitution.js\n// module id = 211\n// module chunks = 0","'use strict';\nvar getBuiltIn = require('../internals/get-built-in');\n\nmodule.exports = getBuiltIn('document', 'documentElement');\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/html.js\n// module id = 212\n// module chunks = 0","'use strict';\nvar DESCRIPTORS = require('../internals/descriptors');\nvar fails = require('../internals/fails');\nvar createElement = require('../internals/document-create-element');\n\n// Thanks to IE8 for its funny defineProperty\nmodule.exports = !DESCRIPTORS && !fails(function () {\n // eslint-disable-next-line es/no-object-defineproperty -- required for testing\n return Object.defineProperty(createElement('div'), 'a', {\n get: function () { return 7; }\n }).a !== 7;\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/ie8-dom-define.js\n// module id = 213\n// module chunks = 0","'use strict';\nvar isObject = require('../internals/is-object');\nvar createNonEnumerableProperty = require('../internals/create-non-enumerable-property');\n\n// `InstallErrorCause` abstract operation\n// https://tc39.es/proposal-error-cause/#sec-errorobjects-install-error-cause\nmodule.exports = function (O, options) {\n if (isObject(options) && 'cause' in options) {\n createNonEnumerableProperty(O, 'cause', options.cause);\n }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/install-error-cause.js\n// module id = 214\n// module chunks = 0","'use strict';\nvar classof = require('../internals/classof');\n\nmodule.exports = function (it) {\n var klass = classof(it);\n return klass === 'BigInt64Array' || klass === 'BigUint64Array';\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/is-big-int-array.js\n// module id = 215\n// module chunks = 0","'use strict';\nvar hasOwn = require('../internals/has-own-property');\n\nmodule.exports = function (descriptor) {\n return descriptor !== undefined && (hasOwn(descriptor, 'value') || hasOwn(descriptor, 'writable'));\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/is-data-descriptor.js\n// module id = 216\n// module chunks = 0","'use strict';\nvar isObject = require('../internals/is-object');\n\nmodule.exports = function (argument) {\n return isObject(argument) || argument === null;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/is-possible-prototype.js\n// module id = 217\n// module chunks = 0","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\n\n// eslint-disable-next-line es/no-map -- safe\nvar MapPrototype = Map.prototype;\n\nmodule.exports = {\n // eslint-disable-next-line es/no-map -- safe\n Map: Map,\n set: uncurryThis(MapPrototype.set),\n get: uncurryThis(MapPrototype.get),\n has: uncurryThis(MapPrototype.has),\n remove: uncurryThis(MapPrototype['delete']),\n proto: MapPrototype\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/map-helpers.js\n// module id = 218\n// module chunks = 0","'use strict';\nvar sign = require('../internals/math-sign');\nvar roundTiesToEven = require('../internals/math-round-ties-to-even');\n\nvar abs = Math.abs;\n\nvar EPSILON = 2.220446049250313e-16; // Number.EPSILON\n\nmodule.exports = function (x, FLOAT_EPSILON, FLOAT_MAX_VALUE, FLOAT_MIN_VALUE) {\n var n = +x;\n var absolute = abs(n);\n var s = sign(n);\n if (absolute < FLOAT_MIN_VALUE) return s * roundTiesToEven(absolute / FLOAT_MIN_VALUE / FLOAT_EPSILON) * FLOAT_MIN_VALUE * FLOAT_EPSILON;\n var a = (1 + FLOAT_EPSILON / EPSILON) * absolute;\n var result = a - (a - absolute);\n // eslint-disable-next-line no-self-compare -- NaN check\n if (result > FLOAT_MAX_VALUE || result !== result) return s * Infinity;\n return s * result;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/math-float-round.js\n// module id = 219\n// module chunks = 0","'use strict';\nvar floatRound = require('../internals/math-float-round');\n\nvar FLOAT32_EPSILON = 1.1920928955078125e-7; // 2 ** -23;\nvar FLOAT32_MAX_VALUE = 3.4028234663852886e+38; // 2 ** 128 - 2 ** 104\nvar FLOAT32_MIN_VALUE = 1.1754943508222875e-38; // 2 ** -126;\n\n// `Math.fround` method implementation\n// https://tc39.es/ecma262/#sec-math.fround\n// eslint-disable-next-line es/no-math-fround -- safe\nmodule.exports = Math.fround || function fround(x) {\n return floatRound(x, FLOAT32_EPSILON, FLOAT32_MAX_VALUE, FLOAT32_MIN_VALUE);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/math-fround.js\n// module id = 220\n// module chunks = 0","'use strict';\nvar log = Math.log;\nvar LOG10E = Math.LOG10E;\n\n// eslint-disable-next-line es/no-math-log10 -- safe\nmodule.exports = Math.log10 || function log10(x) {\n return log(x) * LOG10E;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/math-log10.js\n// module id = 221\n// module chunks = 0","'use strict';\nvar log = Math.log;\n\n// `Math.log1p` method implementation\n// https://tc39.es/ecma262/#sec-math.log1p\n// eslint-disable-next-line es/no-math-log1p -- safe\nmodule.exports = Math.log1p || function log1p(x) {\n var n = +x;\n return n > -1e-8 && n < 1e-8 ? n - n * n / 2 : log(1 + n);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/math-log1p.js\n// module id = 222\n// module chunks = 0","'use strict';\nvar log = Math.log;\nvar LN2 = Math.LN2;\n\n// `Math.log2` method\n// https://tc39.es/ecma262/#sec-math.log2\n// eslint-disable-next-line es/no-math-log2 -- safe\nmodule.exports = Math.log2 || function log2(x) {\n return log(x) / LN2;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/math-log2.js\n// module id = 223\n// module chunks = 0","'use strict';\nvar EPSILON = 2.220446049250313e-16; // Number.EPSILON\nvar INVERSE_EPSILON = 1 / EPSILON;\n\nmodule.exports = function (n) {\n return n + INVERSE_EPSILON - INVERSE_EPSILON;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/math-round-ties-to-even.js\n// module id = 224\n// module chunks = 0","'use strict';\nvar ceil = Math.ceil;\nvar floor = Math.floor;\n\n// `Math.trunc` method\n// https://tc39.es/ecma262/#sec-math.trunc\n// eslint-disable-next-line es/no-math-trunc -- safe\nmodule.exports = Math.trunc || function trunc(x) {\n var n = +x;\n return (n > 0 ? floor : ceil)(n);\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/math-trunc.js\n// module id = 225\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar safeGetBuiltIn = require('../internals/safe-get-built-in');\nvar bind = require('../internals/function-bind-context');\nvar macrotask = require('../internals/task').set;\nvar Queue = require('../internals/queue');\nvar IS_IOS = require('../internals/environment-is-ios');\nvar IS_IOS_PEBBLE = require('../internals/environment-is-ios-pebble');\nvar IS_WEBOS_WEBKIT = require('../internals/environment-is-webos-webkit');\nvar IS_NODE = require('../internals/environment-is-node');\n\nvar MutationObserver = globalThis.MutationObserver || globalThis.WebKitMutationObserver;\nvar document = globalThis.document;\nvar process = globalThis.process;\nvar Promise = globalThis.Promise;\nvar microtask = safeGetBuiltIn('queueMicrotask');\nvar notify, toggle, node, promise, then;\n\n// modern engines have queueMicrotask method\nif (!microtask) {\n var queue = new Queue();\n\n var flush = function () {\n var parent, fn;\n if (IS_NODE && (parent = process.domain)) parent.exit();\n while (fn = queue.get()) try {\n fn();\n } catch (error) {\n if (queue.head) notify();\n throw error;\n }\n if (parent) parent.enter();\n };\n\n // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339\n // also except WebOS Webkit https://github.com/zloirock/core-js/issues/898\n if (!IS_IOS && !IS_NODE && !IS_WEBOS_WEBKIT && MutationObserver && document) {\n toggle = true;\n node = document.createTextNode('');\n new MutationObserver(flush).observe(node, { characterData: true });\n notify = function () {\n node.data = toggle = !toggle;\n };\n // environments with maybe non-completely correct, but existent Promise\n } else if (!IS_IOS_PEBBLE && Promise && Promise.resolve) {\n // Promise.resolve without an argument throws an error in LG WebOS 2\n promise = Promise.resolve(undefined);\n // workaround of WebKit ~ iOS Safari 10.1 bug\n promise.constructor = Promise;\n then = bind(promise.then, promise);\n notify = function () {\n then(flush);\n };\n // Node.js without promises\n } else if (IS_NODE) {\n notify = function () {\n process.nextTick(flush);\n };\n // for other environments - macrotask based on:\n // - setImmediate\n // - MessageChannel\n // - window.postMessage\n // - onreadystatechange\n // - setTimeout\n } else {\n // `webpack` dev server bug on IE global methods - use bind(fn, global)\n macrotask = bind(macrotask, globalThis);\n notify = function () {\n macrotask(flush);\n };\n }\n\n microtask = function (fn) {\n if (!queue.head) notify();\n queue.add(fn);\n };\n}\n\nmodule.exports = microtask;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/microtask.js\n// module id = 226\n// module chunks = 0","'use strict';\nvar $RangeError = RangeError;\n\nmodule.exports = function (it) {\n // eslint-disable-next-line no-self-compare -- NaN check\n if (it === it) return it;\n throw new $RangeError('NaN is not allowed');\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/not-a-nan.js\n// module id = 227\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar fails = require('../internals/fails');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar toString = require('../internals/to-string');\nvar trim = require('../internals/string-trim').trim;\nvar whitespaces = require('../internals/whitespaces');\n\nvar charAt = uncurryThis(''.charAt);\nvar $parseFloat = globalThis.parseFloat;\nvar Symbol = globalThis.Symbol;\nvar ITERATOR = Symbol && Symbol.iterator;\nvar FORCED = 1 / $parseFloat(whitespaces + '-0') !== -Infinity\n // MS Edge 18- broken with boxed symbols\n || (ITERATOR && !fails(function () { $parseFloat(Object(ITERATOR)); }));\n\n// `parseFloat` method\n// https://tc39.es/ecma262/#sec-parsefloat-string\nmodule.exports = FORCED ? function parseFloat(string) {\n var trimmedString = trim(toString(string));\n var result = $parseFloat(trimmedString);\n return result === 0 && charAt(trimmedString, 0) === '-' ? -0 : result;\n} : $parseFloat;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/number-parse-float.js\n// module id = 228\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar fails = require('../internals/fails');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar toString = require('../internals/to-string');\nvar trim = require('../internals/string-trim').trim;\nvar whitespaces = require('../internals/whitespaces');\n\nvar $parseInt = globalThis.parseInt;\nvar Symbol = globalThis.Symbol;\nvar ITERATOR = Symbol && Symbol.iterator;\nvar hex = /^[+-]?0x/i;\nvar exec = uncurryThis(hex.exec);\nvar FORCED = $parseInt(whitespaces + '08') !== 8 || $parseInt(whitespaces + '0x16') !== 22\n // MS Edge 18- broken with boxed symbols\n || (ITERATOR && !fails(function () { $parseInt(Object(ITERATOR)); }));\n\n// `parseInt` method\n// https://tc39.es/ecma262/#sec-parseint-string-radix\nmodule.exports = FORCED ? function parseInt(string, radix) {\n var S = trim(toString(string));\n return $parseInt(S, (radix >>> 0) || (exec(hex, S) ? 16 : 10));\n} : $parseInt;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/number-parse-int.js\n// module id = 229\n// module chunks = 0","'use strict';\nvar DESCRIPTORS = require('../internals/descriptors');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar call = require('../internals/function-call');\nvar fails = require('../internals/fails');\nvar objectKeys = require('../internals/object-keys');\nvar getOwnPropertySymbolsModule = require('../internals/object-get-own-property-symbols');\nvar propertyIsEnumerableModule = require('../internals/object-property-is-enumerable');\nvar toObject = require('../internals/to-object');\nvar IndexedObject = require('../internals/indexed-object');\n\n// eslint-disable-next-line es/no-object-assign -- safe\nvar $assign = Object.assign;\n// eslint-disable-next-line es/no-object-defineproperty -- required for testing\nvar defineProperty = Object.defineProperty;\nvar concat = uncurryThis([].concat);\n\n// `Object.assign` method\n// https://tc39.es/ecma262/#sec-object.assign\nmodule.exports = !$assign || fails(function () {\n // should have correct order of operations (Edge bug)\n if (DESCRIPTORS && $assign({ b: 1 }, $assign(defineProperty({}, 'a', {\n enumerable: true,\n get: function () {\n defineProperty(this, 'b', {\n value: 3,\n enumerable: false\n });\n }\n }), { b: 2 })).b !== 1) return true;\n // should work with symbols and should have deterministic property order (V8 bug)\n var A = {};\n var B = {};\n // eslint-disable-next-line es/no-symbol -- safe\n var symbol = Symbol('assign detection');\n var alphabet = 'abcdefghijklmnopqrst';\n A[symbol] = 7;\n // eslint-disable-next-line es/no-array-prototype-foreach -- safe\n alphabet.split('').forEach(function (chr) { B[chr] = chr; });\n return $assign({}, A)[symbol] !== 7 || objectKeys($assign({}, B)).join('') !== alphabet;\n}) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length`\n var T = toObject(target);\n var argumentsLength = arguments.length;\n var index = 1;\n var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;\n var propertyIsEnumerable = propertyIsEnumerableModule.f;\n while (argumentsLength > index) {\n var S = IndexedObject(arguments[index++]);\n var keys = getOwnPropertySymbols ? concat(objectKeys(S), getOwnPropertySymbols(S)) : objectKeys(S);\n var length = keys.length;\n var j = 0;\n var key;\n while (length > j) {\n key = keys[j++];\n if (!DESCRIPTORS || call(propertyIsEnumerable, S, key)) T[key] = S[key];\n }\n } return T;\n} : $assign;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/object-assign.js\n// module id = 230\n// module chunks = 0","'use strict';\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar hasOwn = require('../internals/has-own-property');\nvar toIndexedObject = require('../internals/to-indexed-object');\nvar indexOf = require('../internals/array-includes').indexOf;\nvar hiddenKeys = require('../internals/hidden-keys');\n\nvar push = uncurryThis([].push);\n\nmodule.exports = function (object, names) {\n var O = toIndexedObject(object);\n var i = 0;\n var result = [];\n var key;\n for (key in O) !hasOwn(hiddenKeys, key) && hasOwn(O, key) && push(result, key);\n // Don't enum bug & hidden keys\n while (names.length > i) if (hasOwn(O, key = names[i++])) {\n ~indexOf(result, key) || push(result, key);\n }\n return result;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/object-keys-internal.js\n// module id = 231\n// module chunks = 0","'use strict';\nvar DESCRIPTORS = require('../internals/descriptors');\nvar fails = require('../internals/fails');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar objectGetPrototypeOf = require('../internals/object-get-prototype-of');\nvar objectKeys = require('../internals/object-keys');\nvar toIndexedObject = require('../internals/to-indexed-object');\nvar $propertyIsEnumerable = require('../internals/object-property-is-enumerable').f;\n\nvar propertyIsEnumerable = uncurryThis($propertyIsEnumerable);\nvar push = uncurryThis([].push);\n\n// in some IE versions, `propertyIsEnumerable` returns incorrect result on integer keys\n// of `null` prototype objects\nvar IE_BUG = DESCRIPTORS && fails(function () {\n // eslint-disable-next-line es/no-object-create -- safe\n var O = Object.create(null);\n O[2] = 2;\n return !propertyIsEnumerable(O, 2);\n});\n\n// `Object.{ entries, values }` methods implementation\nvar createMethod = function (TO_ENTRIES) {\n return function (it) {\n var O = toIndexedObject(it);\n var keys = objectKeys(O);\n var IE_WORKAROUND = IE_BUG && objectGetPrototypeOf(O) === null;\n var length = keys.length;\n var i = 0;\n var result = [];\n var key;\n while (length > i) {\n key = keys[i++];\n if (!DESCRIPTORS || (IE_WORKAROUND ? key in O : propertyIsEnumerable(O, key))) {\n push(result, TO_ENTRIES ? [key, O[key]] : O[key]);\n }\n }\n return result;\n };\n};\n\nmodule.exports = {\n // `Object.entries` method\n // https://tc39.es/ecma262/#sec-object.entries\n entries: createMethod(true),\n // `Object.values` method\n // https://tc39.es/ecma262/#sec-object.values\n values: createMethod(false)\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/object-to-array.js\n// module id = 232\n// module chunks = 0","'use strict';\nvar call = require('../internals/function-call');\nvar isCallable = require('../internals/is-callable');\nvar isObject = require('../internals/is-object');\n\nvar $TypeError = TypeError;\n\n// `OrdinaryToPrimitive` abstract operation\n// https://tc39.es/ecma262/#sec-ordinarytoprimitive\nmodule.exports = function (input, pref) {\n var fn, val;\n if (pref === 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;\n if (isCallable(fn = input.valueOf) && !isObject(val = call(fn, input))) return val;\n if (pref !== 'string' && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;\n throw new $TypeError(\"Can't convert object to primitive value\");\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/ordinary-to-primitive.js\n// module id = 233\n// module chunks = 0","'use strict';\nvar anObject = require('../internals/an-object');\nvar isObject = require('../internals/is-object');\nvar newPromiseCapability = require('../internals/new-promise-capability');\n\nmodule.exports = function (C, x) {\n anObject(C);\n if (isObject(x) && x.constructor === C) return x;\n var promiseCapability = newPromiseCapability.f(C);\n var resolve = promiseCapability.resolve;\n resolve(x);\n return promiseCapability.promise;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/promise-resolve.js\n// module id = 234\n// module chunks = 0","'use strict';\nvar defineProperty = require('../internals/object-define-property').f;\n\nmodule.exports = function (Target, Source, key) {\n key in Target || defineProperty(Target, key, {\n configurable: true,\n get: function () { return Source[key]; },\n set: function (it) { Source[key] = it; }\n });\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/proxy-accessor.js\n// module id = 235\n// module chunks = 0","'use strict';\nvar Queue = function () {\n this.head = null;\n this.tail = null;\n};\n\nQueue.prototype = {\n add: function (item) {\n var entry = { item: item, next: null };\n var tail = this.tail;\n if (tail) tail.next = entry;\n else this.head = entry;\n this.tail = entry;\n },\n get: function () {\n var entry = this.head;\n if (entry) {\n var next = this.head = entry.next;\n if (next === null) this.tail = null;\n return entry.item;\n }\n }\n};\n\nmodule.exports = Queue;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/queue.js\n// module id = 236\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar fails = require('../internals/fails');\n\n// babel-minify and Closure Compiler transpiles RegExp('.', 'd') -> /./d and it causes SyntaxError\nvar RegExp = globalThis.RegExp;\n\nvar FLAGS_GETTER_IS_CORRECT = !fails(function () {\n var INDICES_SUPPORT = true;\n try {\n RegExp('.', 'd');\n } catch (error) {\n INDICES_SUPPORT = false;\n }\n\n var O = {};\n // modern V8 bug\n var calls = '';\n var expected = INDICES_SUPPORT ? 'dgimsy' : 'gimsy';\n\n var addGetter = function (key, chr) {\n // eslint-disable-next-line es/no-object-defineproperty -- safe\n Object.defineProperty(O, key, { get: function () {\n calls += chr;\n return true;\n } });\n };\n\n var pairs = {\n dotAll: 's',\n global: 'g',\n ignoreCase: 'i',\n multiline: 'm',\n sticky: 'y'\n };\n\n if (INDICES_SUPPORT) pairs.hasIndices = 'd';\n\n for (var key in pairs) addGetter(key, pairs[key]);\n\n // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe\n var result = Object.getOwnPropertyDescriptor(RegExp.prototype, 'flags').get.call(O);\n\n return result !== expected || calls !== expected;\n});\n\nmodule.exports = { correct: FLAGS_GETTER_IS_CORRECT };\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/regexp-flags-detection.js\n// module id = 237\n// module chunks = 0","'use strict';\nvar fails = require('../internals/fails');\nvar globalThis = require('../internals/global-this');\n\n// babel-minify and Closure Compiler transpiles RegExp('(?b)', 'g') -> /(?b)/g and it causes SyntaxError\nvar $RegExp = globalThis.RegExp;\n\nmodule.exports = fails(function () {\n var re = $RegExp('(?b)', 'g');\n return re.exec('b').groups.a !== 'b' ||\n 'b'.replace(re, '$c') !== 'bc';\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/regexp-unsupported-ncg.js\n// module id = 238\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar DESCRIPTORS = require('../internals/descriptors');\n\n// eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe\nvar getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n\n// Avoid NodeJS experimental warning\nmodule.exports = function (name) {\n if (!DESCRIPTORS) return globalThis[name];\n var descriptor = getOwnPropertyDescriptor(globalThis, name);\n return descriptor && descriptor.value;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/safe-get-built-in.js\n// module id = 239\n// module chunks = 0","'use strict';\n// `SameValue` abstract operation\n// https://tc39.es/ecma262/#sec-samevalue\n// eslint-disable-next-line es/no-object-is -- safe\nmodule.exports = Object.is || function is(x, y) {\n // eslint-disable-next-line no-self-compare -- NaN check\n return x === y ? x !== 0 || 1 / x === 1 / y : x !== x && y !== y;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/same-value.js\n// module id = 240\n// module chunks = 0","'use strict';\n// Should get iterator record of a set-like object before cloning this\n// https://bugs.webkit.org/show_bug.cgi?id=289430\nmodule.exports = function (METHOD_NAME) {\n try {\n // eslint-disable-next-line es/no-set -- needed for test\n var baseSet = new Set();\n var setLike = {\n size: 0,\n has: function () { return true; },\n keys: function () {\n // eslint-disable-next-line es/no-object-defineproperty -- needed for test\n return Object.defineProperty({}, 'next', {\n get: function () {\n baseSet.clear();\n baseSet.add(4);\n return function () {\n return { done: true };\n };\n }\n });\n }\n };\n var result = baseSet[METHOD_NAME](setLike);\n\n return result.size !== 1 || result.values().next().value !== 4;\n } catch (error) {\n return false;\n }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/set-method-get-keys-before-cloning-detection.js\n// module id = 241\n// module chunks = 0","'use strict';\n// https://github.com/zloirock/core-js/issues/280\nvar userAgent = require('../internals/environment-user-agent');\n\nmodule.exports = /Version\\/10(?:\\.\\d+){1,2}(?: [\\w./]+)?(?: Mobile\\/\\w+)? Safari\\//.test(userAgent);\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/string-pad-webkit-bug.js\n// module id = 242\n// module chunks = 0","'use strict';\nvar $trimEnd = require('../internals/string-trim').end;\nvar forcedStringTrimMethod = require('../internals/string-trim-forced');\n\n// `String.prototype.{ trimEnd, trimRight }` method\n// https://tc39.es/ecma262/#sec-string.prototype.trimend\n// https://tc39.es/ecma262/#String.prototype.trimright\nmodule.exports = forcedStringTrimMethod('trimEnd') ? function trimEnd() {\n return $trimEnd(this);\n// eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe\n} : ''.trimEnd;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/string-trim-end.js\n// module id = 243\n// module chunks = 0","'use strict';\nvar $trimStart = require('../internals/string-trim').start;\nvar forcedStringTrimMethod = require('../internals/string-trim-forced');\n\n// `String.prototype.{ trimStart, trimLeft }` method\n// https://tc39.es/ecma262/#sec-string.prototype.trimstart\n// https://tc39.es/ecma262/#String.prototype.trimleft\nmodule.exports = forcedStringTrimMethod('trimStart') ? function trimStart() {\n return $trimStart(this);\n// eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe\n} : ''.trimStart;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/string-trim-start.js\n// module id = 244\n// module chunks = 0","'use strict';\nvar call = require('../internals/function-call');\nvar getBuiltIn = require('../internals/get-built-in');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\nvar defineBuiltIn = require('../internals/define-built-in');\n\nmodule.exports = function () {\n var Symbol = getBuiltIn('Symbol');\n var SymbolPrototype = Symbol && Symbol.prototype;\n var valueOf = SymbolPrototype && SymbolPrototype.valueOf;\n var TO_PRIMITIVE = wellKnownSymbol('toPrimitive');\n\n if (SymbolPrototype && !SymbolPrototype[TO_PRIMITIVE]) {\n // `Symbol.prototype[@@toPrimitive]` method\n // https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive\n // eslint-disable-next-line no-unused-vars -- required for .length\n defineBuiltIn(SymbolPrototype, TO_PRIMITIVE, function (hint) {\n return call(valueOf, this);\n }, { arity: 1 });\n }\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/symbol-define-to-primitive.js\n// module id = 245\n// module chunks = 0","'use strict';\nvar NATIVE_SYMBOL = require('../internals/symbol-constructor-detection');\n\n/* eslint-disable es/no-symbol -- safe */\nmodule.exports = NATIVE_SYMBOL && !!Symbol['for'] && !!Symbol.keyFor;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/symbol-registry-detection.js\n// module id = 246\n// module chunks = 0","'use strict';\nvar toPositiveInteger = require('../internals/to-positive-integer');\n\nvar $RangeError = RangeError;\n\nmodule.exports = function (it, BYTES) {\n var offset = toPositiveInteger(it);\n if (offset % BYTES) throw new $RangeError('Wrong offset');\n return offset;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/to-offset.js\n// module id = 247\n// module chunks = 0","'use strict';\nvar bind = require('../internals/function-bind-context');\nvar call = require('../internals/function-call');\nvar aConstructor = require('../internals/a-constructor');\nvar toObject = require('../internals/to-object');\nvar lengthOfArrayLike = require('../internals/length-of-array-like');\nvar getIterator = require('../internals/get-iterator');\nvar getIteratorMethod = require('../internals/get-iterator-method');\nvar isArrayIteratorMethod = require('../internals/is-array-iterator-method');\nvar isBigIntArray = require('../internals/is-big-int-array');\nvar aTypedArrayConstructor = require('../internals/array-buffer-view-core').aTypedArrayConstructor;\nvar toBigInt = require('../internals/to-big-int');\n\nmodule.exports = function from(source /* , mapfn, thisArg */) {\n var C = aConstructor(this);\n var O = toObject(source);\n var argumentsLength = arguments.length;\n var mapfn = argumentsLength > 1 ? arguments[1] : undefined;\n var mapping = mapfn !== undefined;\n var iteratorMethod = getIteratorMethod(O);\n var i, length, result, thisIsBigIntArray, value, step, iterator, next;\n if (iteratorMethod && !isArrayIteratorMethod(iteratorMethod)) {\n iterator = getIterator(O, iteratorMethod);\n next = iterator.next;\n O = [];\n while (!(step = call(next, iterator)).done) {\n O.push(step.value);\n }\n }\n if (mapping && argumentsLength > 2) {\n mapfn = bind(mapfn, arguments[2]);\n }\n length = lengthOfArrayLike(O);\n result = new (aTypedArrayConstructor(C))(length);\n thisIsBigIntArray = isBigIntArray(result);\n for (i = 0; length > i; i++) {\n value = mapping ? mapfn(O[i], i) : O[i];\n // FF30- typed arrays doesn't properly convert objects to typed array values\n result[i] = thisIsBigIntArray ? toBigInt(value) : +value;\n }\n return result;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/typed-array-from.js\n// module id = 248\n// module chunks = 0","'use strict';\n/* eslint-disable es/no-symbol -- required for testing */\nvar NATIVE_SYMBOL = require('../internals/symbol-constructor-detection');\n\nmodule.exports = NATIVE_SYMBOL &&\n !Symbol.sham &&\n typeof Symbol.iterator == 'symbol';\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/use-symbol-as-uid.js\n// module id = 249\n// module chunks = 0","'use strict';\nvar DESCRIPTORS = require('../internals/descriptors');\nvar fails = require('../internals/fails');\n\n// V8 ~ Chrome 36-\n// https://bugs.chromium.org/p/v8/issues/detail?id=3334\nmodule.exports = DESCRIPTORS && fails(function () {\n // eslint-disable-next-line es/no-object-defineproperty -- required for testing\n return Object.defineProperty(function () { /* empty */ }, 'prototype', {\n value: 42,\n writable: false\n }).prototype !== 42;\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/v8-prototype-define-bug.js\n// module id = 250\n// module chunks = 0","'use strict';\nvar globalThis = require('../internals/global-this');\nvar isCallable = require('../internals/is-callable');\n\nvar WeakMap = globalThis.WeakMap;\n\nmodule.exports = isCallable(WeakMap) && /native code/.test(String(WeakMap));\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/weak-map-basic-detection.js\n// module id = 251\n// module chunks = 0","'use strict';\nvar wellKnownSymbol = require('../internals/well-known-symbol');\n\nexports.f = wellKnownSymbol;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/well-known-symbol-wrapped.js\n// module id = 252\n// module chunks = 0","'use strict';\nvar getBuiltIn = require('../internals/get-built-in');\nvar hasOwn = require('../internals/has-own-property');\nvar createNonEnumerableProperty = require('../internals/create-non-enumerable-property');\nvar isPrototypeOf = require('../internals/object-is-prototype-of');\nvar setPrototypeOf = require('../internals/object-set-prototype-of');\nvar copyConstructorProperties = require('../internals/copy-constructor-properties');\nvar proxyAccessor = require('../internals/proxy-accessor');\nvar inheritIfRequired = require('../internals/inherit-if-required');\nvar normalizeStringArgument = require('../internals/normalize-string-argument');\nvar installErrorCause = require('../internals/install-error-cause');\nvar installErrorStack = require('../internals/error-stack-install');\nvar DESCRIPTORS = require('../internals/descriptors');\nvar IS_PURE = require('../internals/is-pure');\n\nmodule.exports = function (FULL_NAME, wrapper, FORCED, IS_AGGREGATE_ERROR) {\n var STACK_TRACE_LIMIT = 'stackTraceLimit';\n var OPTIONS_POSITION = IS_AGGREGATE_ERROR ? 2 : 1;\n var path = FULL_NAME.split('.');\n var ERROR_NAME = path[path.length - 1];\n var OriginalError = getBuiltIn.apply(null, path);\n\n if (!OriginalError) return;\n\n var OriginalErrorPrototype = OriginalError.prototype;\n\n // V8 9.3- bug https://bugs.chromium.org/p/v8/issues/detail?id=12006\n if (!IS_PURE && hasOwn(OriginalErrorPrototype, 'cause')) delete OriginalErrorPrototype.cause;\n\n if (!FORCED) return OriginalError;\n\n var BaseError = getBuiltIn('Error');\n\n var WrappedError = wrapper(function (a, b) {\n var message = normalizeStringArgument(IS_AGGREGATE_ERROR ? b : a, undefined);\n var result = IS_AGGREGATE_ERROR ? new OriginalError(a) : new OriginalError();\n if (message !== undefined) createNonEnumerableProperty(result, 'message', message);\n installErrorStack(result, WrappedError, result.stack, 2);\n if (this && isPrototypeOf(OriginalErrorPrototype, this)) inheritIfRequired(result, this, WrappedError);\n if (arguments.length > OPTIONS_POSITION) installErrorCause(result, arguments[OPTIONS_POSITION]);\n return result;\n });\n\n WrappedError.prototype = OriginalErrorPrototype;\n\n if (ERROR_NAME !== 'Error') {\n if (setPrototypeOf) setPrototypeOf(WrappedError, BaseError);\n else copyConstructorProperties(WrappedError, BaseError, { name: true });\n } else if (DESCRIPTORS && STACK_TRACE_LIMIT in OriginalError) {\n proxyAccessor(WrappedError, OriginalError, STACK_TRACE_LIMIT);\n proxyAccessor(WrappedError, OriginalError, 'prepareStackTrace');\n }\n\n copyConstructorProperties(WrappedError, OriginalError);\n\n if (!IS_PURE) try {\n // Safari 13- bug: WebAssembly errors does not have a proper `.name`\n if (OriginalErrorPrototype.name !== ERROR_NAME) {\n createNonEnumerableProperty(OriginalErrorPrototype, 'name', ERROR_NAME);\n }\n OriginalErrorPrototype.constructor = WrappedError;\n } catch (error) { /* empty */ }\n\n return WrappedError;\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/internals/wrap-error-constructor-with-cause.js\n// module id = 253\n// module chunks = 0","'use strict';\nvar $ = require('../internals/export');\nvar getBuiltIn = require('../internals/get-built-in');\nvar apply = require('../internals/function-apply');\nvar call = require('../internals/function-call');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar fails = require('../internals/fails');\nvar isCallable = require('../internals/is-callable');\nvar isSymbol = require('../internals/is-symbol');\nvar arraySlice = require('../internals/array-slice');\nvar getReplacerFunction = require('../internals/get-json-replacer-function');\nvar NATIVE_SYMBOL = require('../internals/symbol-constructor-detection');\n\nvar $String = String;\nvar $stringify = getBuiltIn('JSON', 'stringify');\nvar exec = uncurryThis(/./.exec);\nvar charAt = uncurryThis(''.charAt);\nvar charCodeAt = uncurryThis(''.charCodeAt);\nvar replace = uncurryThis(''.replace);\nvar numberToString = uncurryThis(1.1.toString);\n\nvar tester = /[\\uD800-\\uDFFF]/g;\nvar low = /^[\\uD800-\\uDBFF]$/;\nvar hi = /^[\\uDC00-\\uDFFF]$/;\n\nvar WRONG_SYMBOLS_CONVERSION = !NATIVE_SYMBOL || fails(function () {\n var symbol = getBuiltIn('Symbol')('stringify detection');\n // MS Edge converts symbol values to JSON as {}\n return $stringify([symbol]) !== '[null]'\n // WebKit converts symbol values to JSON as null\n || $stringify({ a: symbol }) !== '{}'\n // V8 throws on boxed symbols\n || $stringify(Object(symbol)) !== '{}';\n});\n\n// https://github.com/tc39/proposal-well-formed-stringify\nvar ILL_FORMED_UNICODE = fails(function () {\n return $stringify('\\uDF06\\uD834') !== '\"\\\\udf06\\\\ud834\"'\n || $stringify('\\uDEAD') !== '\"\\\\udead\"';\n});\n\nvar stringifyWithSymbolsFix = function (it, replacer) {\n var args = arraySlice(arguments);\n var $replacer = getReplacerFunction(replacer);\n if (!isCallable($replacer) && (it === undefined || isSymbol(it))) return; // IE8 returns string on undefined\n args[1] = function (key, value) {\n // some old implementations (like WebKit) could pass numbers as keys\n if (isCallable($replacer)) value = call($replacer, this, $String(key), value);\n if (!isSymbol(value)) return value;\n };\n return apply($stringify, null, args);\n};\n\nvar fixIllFormed = function (match, offset, string) {\n var prev = charAt(string, offset - 1);\n var next = charAt(string, offset + 1);\n if ((exec(low, match) && !exec(hi, next)) || (exec(hi, match) && !exec(low, prev))) {\n return '\\\\u' + numberToString(charCodeAt(match, 0), 16);\n } return match;\n};\n\nif ($stringify) {\n // `JSON.stringify` method\n // https://tc39.es/ecma262/#sec-json.stringify\n $({ target: 'JSON', stat: true, arity: 3, forced: WRONG_SYMBOLS_CONVERSION || ILL_FORMED_UNICODE }, {\n // eslint-disable-next-line no-unused-vars -- required for `.length`\n stringify: function stringify(it, replacer, space) {\n var args = arraySlice(arguments);\n var result = apply(WRONG_SYMBOLS_CONVERSION ? stringifyWithSymbolsFix : $stringify, null, args);\n return ILL_FORMED_UNICODE && typeof result == 'string' ? replace(result, tester, fixIllFormed) : result;\n }\n });\n}\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es.json.stringify.js\n// module id = 254\n// module chunks = 0","'use strict';\nvar $ = require('../internals/export');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar toAbsoluteIndex = require('../internals/to-absolute-index');\n\nvar $RangeError = RangeError;\nvar fromCharCode = String.fromCharCode;\n// eslint-disable-next-line es/no-string-fromcodepoint -- required for testing\nvar $fromCodePoint = String.fromCodePoint;\nvar join = uncurryThis([].join);\n\n// length should be 1, old FF problem\nvar INCORRECT_LENGTH = !!$fromCodePoint && $fromCodePoint.length !== 1;\n\n// `String.fromCodePoint` method\n// https://tc39.es/ecma262/#sec-string.fromcodepoint\n$({ target: 'String', stat: true, arity: 1, forced: INCORRECT_LENGTH }, {\n // eslint-disable-next-line no-unused-vars -- required for `.length`\n fromCodePoint: function fromCodePoint(x) {\n var elements = [];\n var length = arguments.length;\n var i = 0;\n var code;\n while (length > i) {\n code = +arguments[i++];\n if (toAbsoluteIndex(code, 0x10FFFF) !== code) throw new $RangeError(code + ' is not a valid code point');\n elements[i] = code < 0x10000\n ? fromCharCode(code)\n : fromCharCode(((code -= 0x10000) >> 10) + 0xD800, code % 0x400 + 0xDC00);\n } return join(elements, '');\n }\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es.string.from-code-point.js\n// module id = 255\n// module chunks = 0","'use strict';\nvar charAt = require('../internals/string-multibyte').charAt;\nvar toString = require('../internals/to-string');\nvar InternalStateModule = require('../internals/internal-state');\nvar defineIterator = require('../internals/iterator-define');\nvar createIterResultObject = require('../internals/create-iter-result-object');\n\nvar STRING_ITERATOR = 'String Iterator';\nvar setInternalState = InternalStateModule.set;\nvar getInternalState = InternalStateModule.getterFor(STRING_ITERATOR);\n\n// `String.prototype[@@iterator]` method\n// https://tc39.es/ecma262/#sec-string.prototype-@@iterator\ndefineIterator(String, 'String', function (iterated) {\n setInternalState(this, {\n type: STRING_ITERATOR,\n string: toString(iterated),\n index: 0\n });\n// `%StringIteratorPrototype%.next` method\n// https://tc39.es/ecma262/#sec-%stringiteratorprototype%.next\n}, function next() {\n var state = getInternalState(this);\n var string = state.string;\n var index = state.index;\n var point;\n if (index >= string.length) return createIterResultObject(undefined, true);\n point = charAt(string, index);\n state.index += point.length;\n return createIterResultObject(point, false);\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/es.string.iterator.js\n// module id = 256\n// module chunks = 0","'use strict';\n// TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env`\nrequire('../modules/es.array.iterator');\nrequire('../modules/es.string.from-code-point');\nvar $ = require('../internals/export');\nvar globalThis = require('../internals/global-this');\nvar safeGetBuiltIn = require('../internals/safe-get-built-in');\nvar getBuiltIn = require('../internals/get-built-in');\nvar call = require('../internals/function-call');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar DESCRIPTORS = require('../internals/descriptors');\nvar USE_NATIVE_URL = require('../internals/url-constructor-detection');\nvar defineBuiltIn = require('../internals/define-built-in');\nvar defineBuiltInAccessor = require('../internals/define-built-in-accessor');\nvar defineBuiltIns = require('../internals/define-built-ins');\nvar setToStringTag = require('../internals/set-to-string-tag');\nvar createIteratorConstructor = require('../internals/iterator-create-constructor');\nvar InternalStateModule = require('../internals/internal-state');\nvar anInstance = require('../internals/an-instance');\nvar isCallable = require('../internals/is-callable');\nvar hasOwn = require('../internals/has-own-property');\nvar bind = require('../internals/function-bind-context');\nvar classof = require('../internals/classof');\nvar anObject = require('../internals/an-object');\nvar isObject = require('../internals/is-object');\nvar $toString = require('../internals/to-string');\nvar create = require('../internals/object-create');\nvar createPropertyDescriptor = require('../internals/create-property-descriptor');\nvar getIterator = require('../internals/get-iterator');\nvar getIteratorMethod = require('../internals/get-iterator-method');\nvar createIterResultObject = require('../internals/create-iter-result-object');\nvar validateArgumentsLength = require('../internals/validate-arguments-length');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\nvar arraySort = require('../internals/array-sort');\n\nvar ITERATOR = wellKnownSymbol('iterator');\nvar URL_SEARCH_PARAMS = 'URLSearchParams';\nvar URL_SEARCH_PARAMS_ITERATOR = URL_SEARCH_PARAMS + 'Iterator';\nvar setInternalState = InternalStateModule.set;\nvar getInternalParamsState = InternalStateModule.getterFor(URL_SEARCH_PARAMS);\nvar getInternalIteratorState = InternalStateModule.getterFor(URL_SEARCH_PARAMS_ITERATOR);\n\nvar nativeFetch = safeGetBuiltIn('fetch');\nvar NativeRequest = safeGetBuiltIn('Request');\nvar Headers = safeGetBuiltIn('Headers');\nvar RequestPrototype = NativeRequest && NativeRequest.prototype;\nvar HeadersPrototype = Headers && Headers.prototype;\nvar TypeError = globalThis.TypeError;\nvar encodeURIComponent = globalThis.encodeURIComponent;\nvar fromCharCode = String.fromCharCode;\nvar fromCodePoint = getBuiltIn('String', 'fromCodePoint');\nvar $parseInt = parseInt;\nvar charAt = uncurryThis(''.charAt);\nvar join = uncurryThis([].join);\nvar push = uncurryThis([].push);\nvar replace = uncurryThis(''.replace);\nvar shift = uncurryThis([].shift);\nvar splice = uncurryThis([].splice);\nvar split = uncurryThis(''.split);\nvar stringSlice = uncurryThis(''.slice);\nvar exec = uncurryThis(/./.exec);\n\nvar plus = /\\+/g;\nvar FALLBACK_REPLACER = '\\uFFFD';\nvar VALID_HEX = /^[0-9a-f]+$/i;\n\nvar parseHexOctet = function (string, start) {\n var substr = stringSlice(string, start, start + 2);\n if (!exec(VALID_HEX, substr)) return NaN;\n\n return $parseInt(substr, 16);\n};\n\nvar getLeadingOnes = function (octet) {\n var count = 0;\n for (var mask = 0x80; mask > 0 && (octet & mask) !== 0; mask >>= 1) {\n count++;\n }\n return count;\n};\n\nvar utf8Decode = function (octets) {\n var codePoint = null;\n\n switch (octets.length) {\n case 1:\n codePoint = octets[0];\n break;\n case 2:\n codePoint = (octets[0] & 0x1F) << 6 | (octets[1] & 0x3F);\n break;\n case 3:\n codePoint = (octets[0] & 0x0F) << 12 | (octets[1] & 0x3F) << 6 | (octets[2] & 0x3F);\n break;\n case 4:\n codePoint = (octets[0] & 0x07) << 18 | (octets[1] & 0x3F) << 12 | (octets[2] & 0x3F) << 6 | (octets[3] & 0x3F);\n break;\n }\n\n return codePoint > 0x10FFFF ? null : codePoint;\n};\n\nvar decode = function (input) {\n input = replace(input, plus, ' ');\n var length = input.length;\n var result = '';\n var i = 0;\n\n while (i < length) {\n var decodedChar = charAt(input, i);\n\n if (decodedChar === '%') {\n if (charAt(input, i + 1) === '%' || i + 3 > length) {\n result += '%';\n i++;\n continue;\n }\n\n var octet = parseHexOctet(input, i + 1);\n\n // eslint-disable-next-line no-self-compare -- NaN check\n if (octet !== octet) {\n result += decodedChar;\n i++;\n continue;\n }\n\n i += 2;\n var byteSequenceLength = getLeadingOnes(octet);\n\n if (byteSequenceLength === 0) {\n decodedChar = fromCharCode(octet);\n } else {\n if (byteSequenceLength === 1 || byteSequenceLength > 4) {\n result += FALLBACK_REPLACER;\n i++;\n continue;\n }\n\n var octets = [octet];\n var sequenceIndex = 1;\n\n while (sequenceIndex < byteSequenceLength) {\n i++;\n if (i + 3 > length || charAt(input, i) !== '%') break;\n\n var nextByte = parseHexOctet(input, i + 1);\n\n // eslint-disable-next-line no-self-compare -- NaN check\n if (nextByte !== nextByte) {\n i += 3;\n break;\n }\n if (nextByte > 191 || nextByte < 128) break;\n\n push(octets, nextByte);\n i += 2;\n sequenceIndex++;\n }\n\n if (octets.length !== byteSequenceLength) {\n result += FALLBACK_REPLACER;\n continue;\n }\n\n var codePoint = utf8Decode(octets);\n if (codePoint === null) {\n result += FALLBACK_REPLACER;\n } else {\n decodedChar = fromCodePoint(codePoint);\n }\n }\n }\n\n result += decodedChar;\n i++;\n }\n\n return result;\n};\n\nvar find = /[!'()~]|%20/g;\n\nvar replacements = {\n '!': '%21',\n \"'\": '%27',\n '(': '%28',\n ')': '%29',\n '~': '%7E',\n '%20': '+'\n};\n\nvar replacer = function (match) {\n return replacements[match];\n};\n\nvar serialize = function (it) {\n return replace(encodeURIComponent(it), find, replacer);\n};\n\nvar URLSearchParamsIterator = createIteratorConstructor(function Iterator(params, kind) {\n setInternalState(this, {\n type: URL_SEARCH_PARAMS_ITERATOR,\n target: getInternalParamsState(params).entries,\n index: 0,\n kind: kind\n });\n}, URL_SEARCH_PARAMS, function next() {\n var state = getInternalIteratorState(this);\n var target = state.target;\n var index = state.index++;\n if (!target || index >= target.length) {\n state.target = null;\n return createIterResultObject(undefined, true);\n }\n var entry = target[index];\n switch (state.kind) {\n case 'keys': return createIterResultObject(entry.key, false);\n case 'values': return createIterResultObject(entry.value, false);\n } return createIterResultObject([entry.key, entry.value], false);\n}, true);\n\nvar URLSearchParamsState = function (init) {\n this.entries = [];\n this.url = null;\n\n if (init !== undefined) {\n if (isObject(init)) this.parseObject(init);\n else this.parseQuery(typeof init == 'string' ? charAt(init, 0) === '?' ? stringSlice(init, 1) : init : $toString(init));\n }\n};\n\nURLSearchParamsState.prototype = {\n type: URL_SEARCH_PARAMS,\n bindURL: function (url) {\n this.url = url;\n this.update();\n },\n parseObject: function (object) {\n var entries = this.entries;\n var iteratorMethod = getIteratorMethod(object);\n var iterator, next, step, entryIterator, entryNext, first, second;\n\n if (iteratorMethod) {\n iterator = getIterator(object, iteratorMethod);\n next = iterator.next;\n while (!(step = call(next, iterator)).done) {\n entryIterator = getIterator(anObject(step.value));\n entryNext = entryIterator.next;\n if (\n (first = call(entryNext, entryIterator)).done ||\n (second = call(entryNext, entryIterator)).done ||\n !call(entryNext, entryIterator).done\n ) throw new TypeError('Expected sequence with length 2');\n push(entries, { key: $toString(first.value), value: $toString(second.value) });\n }\n } else for (var key in object) if (hasOwn(object, key)) {\n push(entries, { key: key, value: $toString(object[key]) });\n }\n },\n parseQuery: function (query) {\n if (query) {\n var entries = this.entries;\n var attributes = split(query, '&');\n var index = 0;\n var attribute, entry;\n while (index < attributes.length) {\n attribute = attributes[index++];\n if (attribute.length) {\n entry = split(attribute, '=');\n push(entries, {\n key: decode(shift(entry)),\n value: decode(join(entry, '='))\n });\n }\n }\n }\n },\n serialize: function () {\n var entries = this.entries;\n var result = [];\n var index = 0;\n var entry;\n while (index < entries.length) {\n entry = entries[index++];\n push(result, serialize(entry.key) + '=' + serialize(entry.value));\n } return join(result, '&');\n },\n update: function () {\n this.entries.length = 0;\n this.parseQuery(this.url.query);\n },\n updateURL: function () {\n if (this.url) this.url.update();\n }\n};\n\n// `URLSearchParams` constructor\n// https://url.spec.whatwg.org/#interface-urlsearchparams\nvar URLSearchParamsConstructor = function URLSearchParams(/* init */) {\n anInstance(this, URLSearchParamsPrototype);\n var init = arguments.length > 0 ? arguments[0] : undefined;\n var state = setInternalState(this, new URLSearchParamsState(init));\n if (!DESCRIPTORS) this.size = state.entries.length;\n};\n\nvar URLSearchParamsPrototype = URLSearchParamsConstructor.prototype;\n\ndefineBuiltIns(URLSearchParamsPrototype, {\n // `URLSearchParams.prototype.append` method\n // https://url.spec.whatwg.org/#dom-urlsearchparams-append\n append: function append(name, value) {\n var state = getInternalParamsState(this);\n validateArgumentsLength(arguments.length, 2);\n push(state.entries, { key: $toString(name), value: $toString(value) });\n if (!DESCRIPTORS) this.length++;\n state.updateURL();\n },\n // `URLSearchParams.prototype.delete` method\n // https://url.spec.whatwg.org/#dom-urlsearchparams-delete\n 'delete': function (name /* , value */) {\n var state = getInternalParamsState(this);\n var length = validateArgumentsLength(arguments.length, 1);\n var entries = state.entries;\n var key = $toString(name);\n var $value = length < 2 ? undefined : arguments[1];\n var value = $value === undefined ? $value : $toString($value);\n var index = 0;\n while (index < entries.length) {\n var entry = entries[index];\n if (entry.key === key && (value === undefined || entry.value === value)) {\n splice(entries, index, 1);\n if (value !== undefined) break;\n } else index++;\n }\n if (!DESCRIPTORS) this.size = entries.length;\n state.updateURL();\n },\n // `URLSearchParams.prototype.get` method\n // https://url.spec.whatwg.org/#dom-urlsearchparams-get\n get: function get(name) {\n var entries = getInternalParamsState(this).entries;\n validateArgumentsLength(arguments.length, 1);\n var key = $toString(name);\n var index = 0;\n for (; index < entries.length; index++) {\n if (entries[index].key === key) return entries[index].value;\n }\n return null;\n },\n // `URLSearchParams.prototype.getAll` method\n // https://url.spec.whatwg.org/#dom-urlsearchparams-getall\n getAll: function getAll(name) {\n var entries = getInternalParamsState(this).entries;\n validateArgumentsLength(arguments.length, 1);\n var key = $toString(name);\n var result = [];\n var index = 0;\n for (; index < entries.length; index++) {\n if (entries[index].key === key) push(result, entries[index].value);\n }\n return result;\n },\n // `URLSearchParams.prototype.has` method\n // https://url.spec.whatwg.org/#dom-urlsearchparams-has\n has: function has(name /* , value */) {\n var entries = getInternalParamsState(this).entries;\n var length = validateArgumentsLength(arguments.length, 1);\n var key = $toString(name);\n var $value = length < 2 ? undefined : arguments[1];\n var value = $value === undefined ? $value : $toString($value);\n var index = 0;\n while (index < entries.length) {\n var entry = entries[index++];\n if (entry.key === key && (value === undefined || entry.value === value)) return true;\n }\n return false;\n },\n // `URLSearchParams.prototype.set` method\n // https://url.spec.whatwg.org/#dom-urlsearchparams-set\n set: function set(name, value) {\n var state = getInternalParamsState(this);\n validateArgumentsLength(arguments.length, 1);\n var entries = state.entries;\n var found = false;\n var key = $toString(name);\n var val = $toString(value);\n var index = 0;\n var entry;\n for (; index < entries.length; index++) {\n entry = entries[index];\n if (entry.key === key) {\n if (found) splice(entries, index--, 1);\n else {\n found = true;\n entry.value = val;\n }\n }\n }\n if (!found) push(entries, { key: key, value: val });\n if (!DESCRIPTORS) this.size = entries.length;\n state.updateURL();\n },\n // `URLSearchParams.prototype.sort` method\n // https://url.spec.whatwg.org/#dom-urlsearchparams-sort\n sort: function sort() {\n var state = getInternalParamsState(this);\n arraySort(state.entries, function (a, b) {\n return a.key > b.key ? 1 : -1;\n });\n state.updateURL();\n },\n // `URLSearchParams.prototype.forEach` method\n forEach: function forEach(callback /* , thisArg */) {\n var entries = getInternalParamsState(this).entries;\n var boundFunction = bind(callback, arguments.length > 1 ? arguments[1] : undefined);\n var index = 0;\n var entry;\n while (index < entries.length) {\n entry = entries[index++];\n boundFunction(entry.value, entry.key, this);\n }\n },\n // `URLSearchParams.prototype.keys` method\n keys: function keys() {\n return new URLSearchParamsIterator(this, 'keys');\n },\n // `URLSearchParams.prototype.values` method\n values: function values() {\n return new URLSearchParamsIterator(this, 'values');\n },\n // `URLSearchParams.prototype.entries` method\n entries: function entries() {\n return new URLSearchParamsIterator(this, 'entries');\n }\n}, { enumerable: true });\n\n// `URLSearchParams.prototype[@@iterator]` method\ndefineBuiltIn(URLSearchParamsPrototype, ITERATOR, URLSearchParamsPrototype.entries, { name: 'entries' });\n\n// `URLSearchParams.prototype.toString` method\n// https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior\ndefineBuiltIn(URLSearchParamsPrototype, 'toString', function toString() {\n return getInternalParamsState(this).serialize();\n}, { enumerable: true });\n\n// `URLSearchParams.prototype.size` getter\n// https://github.com/whatwg/url/pull/734\nif (DESCRIPTORS) defineBuiltInAccessor(URLSearchParamsPrototype, 'size', {\n get: function size() {\n return getInternalParamsState(this).entries.length;\n },\n configurable: true,\n enumerable: true\n});\n\nsetToStringTag(URLSearchParamsConstructor, URL_SEARCH_PARAMS);\n\n$({ global: true, constructor: true, forced: !USE_NATIVE_URL }, {\n URLSearchParams: URLSearchParamsConstructor\n});\n\n// Wrap `fetch` and `Request` for correct work with polyfilled `URLSearchParams`\nif (!USE_NATIVE_URL && isCallable(Headers)) {\n var headersHas = uncurryThis(HeadersPrototype.has);\n var headersSet = uncurryThis(HeadersPrototype.set);\n\n var wrapRequestOptions = function (init) {\n if (isObject(init)) {\n var body = init.body;\n var headers;\n if (classof(body) === URL_SEARCH_PARAMS) {\n headers = init.headers ? new Headers(init.headers) : new Headers();\n if (!headersHas(headers, 'content-type')) {\n headersSet(headers, 'content-type', 'application/x-www-form-urlencoded;charset=UTF-8');\n }\n return create(init, {\n body: createPropertyDescriptor(0, $toString(body)),\n headers: createPropertyDescriptor(0, headers)\n });\n }\n } return init;\n };\n\n if (isCallable(nativeFetch)) {\n $({ global: true, enumerable: true, dontCallGetSet: true, forced: true }, {\n fetch: function fetch(input /* , init */) {\n return nativeFetch(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});\n }\n });\n }\n\n if (isCallable(NativeRequest)) {\n var RequestConstructor = function Request(input /* , init */) {\n anInstance(this, RequestPrototype);\n return new NativeRequest(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});\n };\n\n RequestPrototype.constructor = RequestConstructor;\n RequestConstructor.prototype = RequestPrototype;\n\n $({ global: true, constructor: true, dontCallGetSet: true, forced: true }, {\n Request: RequestConstructor\n });\n }\n}\n\nmodule.exports = {\n URLSearchParams: URLSearchParamsConstructor,\n getState: getInternalParamsState\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/core-js/modules/web.url-search-params.constructor.js\n// module id = 257\n// module chunks = 0","'use strict';\n\n/**\n* FUNCTION: isArray( value )\n*\tValidates if a value is an array.\n*\n* @param {*} value - value to be validated\n* @returns {Boolean} boolean indicating whether value is an array\n*/\nfunction isArray( value ) {\n\treturn Object.prototype.toString.call( value ) === '[object Array]';\n} // end FUNCTION isArray()\n\n// EXPORTS //\n\nmodule.exports = Array.isArray || isArray;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/validate.io-array/lib/index.js\n// module id = 258\n// module chunks = 0","var g;\r\n\r\n// This works in non-strict mode\r\ng = (function() {\r\n\treturn this;\r\n})();\r\n\r\ntry {\r\n\t// This works if eval is allowed (see CSP)\r\n\tg = g || Function(\"return this\")() || (1,eval)(\"this\");\r\n} catch(e) {\r\n\t// This works if the window reference is available\r\n\tif(typeof window === \"object\")\r\n\t\tg = window;\r\n}\r\n\r\n// g can still be undefined, but nothing to do about it...\r\n// We return undefined, instead of nothing here, so it's\r\n// easier to handle this case. if(!global) { ...}\r\n\r\nmodule.exports = g;\r\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// (webpack)/buildin/global.js\n// module id = 259\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/**\n * Iquizeles color generator\n * @module lib/color.js;\n */\n\nvar palettes = [[[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.0, 0.33, 0.67]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.0, 0.1, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 1.0], [0.3, 0.2, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 1.0, 0.5], [0.8, 0.9, 0.3]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [1.0, 0.7, 0.4], [0.0, 0.15, 0.2]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [2.0, 1.0, 0.0], [0.5, 0.2, 0.25]], [[0.8, 0.5, 0.4], [0.2, 0.4, 0.2], [2.0, 1.0, 1.0], [0.0, 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 = 260\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _tone = require(\"tone\");\n\nvar _tone2 = _interopRequireDefault(_tone);\n\nvar _util = require(\"./util\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Kalimba\n * @module lib/kalimba.js;\n */\n\nvar player_count = 4;\n\nvar samples = [{ root: 219.5, fn: \"samples/380737__cabled-mess__sansula-01-a-raw.wav\" }, { root: 260.9, fn: \"samples/380736__cabled-mess__sansula-02-c-raw.wav\" }, { root: 330.2, fn: \"samples/380735__cabled-mess__sansula-03-e-raw.wav\" }];\n\nfunction load(_ref) {\n var output = _ref.output;\n\n samples.forEach(function (sample) {\n sample.players = [];\n sample.index = -1;\n for (var i = 0; i < player_count; i++) {\n var fn = sample.fn;\n if (window.location.href.match(/asdf.us/)) {\n fn = \"//asdf.us/kalimba/\" + fn.replace(\"wav\", \"mp3\");\n }\n var player = new _tone2.default.Player({\n url: fn,\n retrigger: true,\n playbackRate: 1\n });\n player.name = fn;\n var gain = new _tone2.default.Gain(1.6);\n player.connect(gain);\n gain.connect(output);\n sample.players.push(player);\n }\n });\n console.log(\"+ Voices:\", samples.reduce(function (count, sample) {\n return count + sample.players.length;\n }, 0));\n}\n\nfunction play(interval, root) {\n var sample = (0, _util.choice)(samples);\n sample.index = (sample.index + 1) % sample.players.length;\n\n var player = sample.players[sample.index];\n player.playbackRate = interval * root / sample.root;\n player.start();\n}\n\nfunction pause() {\n // no-op\n}\n\nexports.default = { load: load, play: play, pause: pause };\n\n// for help tuning the kalimba samples\n// function keydown(e) {\n// // console.log(e.keyCode)\n// if (e.metaKey && last) {\n// let step = e.shiftKey ? (e.ctrlKey ? 0.01 : 0.1) : 1;\n// switch (e.keyCode) {\n// case 38: // up\n// e.preventDefault();\n// samples[0].root -= step;\n// play(last);\n// break;\n// case 40: // down\n// e.preventDefault();\n// samples[0].root += step;\n// play(last);\n// break;\n// }\n// console.log(samples[0].root);\n// }\n// }\n// window.addEventListener(\"keydown\", keydown, true);\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/kalimba.js\n// module id = 261\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/**\n * Keyboard helper\n * @module lib/keys.js;\n */\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 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 = 262\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _webmidi = require(\"webmidi\");\n\nfunction enable(play) {\n _webmidi.WebMidi.enable().then(onEnabled).catch(function (error) {\n return console.error(error);\n });\n\n // Function triggered when WEBMIDI.js is ready\n function onEnabled() {\n // Display available MIDI input devices\n if (_webmidi.WebMidi.inputs.length < 1) {\n console.log(\"No device detected.\");\n return;\n } else {\n _webmidi.WebMidi.inputs.forEach(function (device, index) {\n document.body.innerHTML += index + \": \" + device.name + \"
\";\n });\n var mySynth = _webmidi.WebMidi.inputs[0];\n // const mySynth = WebMidi.getInputByName(\"TYPE NAME HERE!\")\n\n mySynth.channels[1].addListener(\"noteon\", function (event) {\n console.log(event.note);\n });\n }\n }\n} /**\n * MIDI\n * @module midi.js;\n */\n\nexports.default = { enable: enable };\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/midi.js\n// module id = 263\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _tone = require(\"tone\");\n\nvar _tone2 = _interopRequireDefault(_tone);\n\nvar _util = require(\"./util\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Sine wave organ\n * @module lib/organ.js;\n */\n\nvar root = 440;\n\nvar oscillators = {};\nvar output = void 0;\nvar lastPlayed = void 0;\n\nfunction load(out) {\n output = out;\n}\nfunction isPlaying(interval) {\n var rounded = (0, _util.roundInterval)(interval);\n var osc = oscillators[rounded];\n return osc && osc.playing;\n}\nfunction play(interval) {\n if (!output) {\n return;\n }\n var rounded = (0, _util.roundInterval)(interval);\n var osc = oscillators[rounded] = oscillators[rounded] || {};\n if (!osc.el) {\n osc.interval = interval;\n osc.el = new _tone2.default.Oscillator(interval * root, \"sine\");\n osc.el.connect(output);\n }\n osc.el.start();\n osc.playing = true;\n lastPlayed = osc;\n return osc;\n}\n\nfunction pause(interval) {\n var rounded = (0, _util.roundInterval)(interval);\n if (!oscillators[rounded]) return;\n var osc = oscillators[rounded] = oscillators[rounded] || {};\n if (osc.el) {\n osc.el.stop();\n }\n osc.playing = false;\n return osc;\n}\n\nfunction setRoot(newRoot) {\n root = newRoot;\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = Object.values(oscillators)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var osc = _step.value;\n\n osc.el.frequency.value = osc.interval * newRoot;\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n}\nfunction stop() {\n var _iteratorNormalCompletion2 = true;\n var _didIteratorError2 = false;\n var _iteratorError2 = undefined;\n\n try {\n for (var _iterator2 = Object.values(oscillators)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {\n var osc = _step2.value;\n\n osc.el.stop();\n osc.el.disconnect();\n osc.playing = false;\n delete osc.el;\n }\n } catch (err) {\n _didIteratorError2 = true;\n _iteratorError2 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion2 && _iterator2.return) {\n _iterator2.return();\n }\n } finally {\n if (_didIteratorError2) {\n throw _iteratorError2;\n }\n }\n }\n\n oscillators = {};\n}\n\nexports.default = { load: load, isPlaying: isPlaying, play: play, pause: pause, stop: stop, setRoot: setRoot };\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/organ.js\n// module id = 264\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.getOutput = getOutput;\n\nvar _tone = require(\"tone\");\n\nvar _tone2 = _interopRequireDefault(_tone);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar output = null; /**\n * Common output stage\n * @module lib/output.js;\n */\n\nfunction getOutput() {\n if (!output) output = makeOutput();\n return output;\n}\n\nfunction makeOutput() {\n var compressor = new _tone2.default.Compressor(-30, 3);\n var gain = new _tone2.default.Gain(0.3);\n compressor.connect(gain);\n gain.toMaster();\n\n return compressor;\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/output.js\n// module id = 265\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.load = load;\nexports.dragOver = dragOver;\nexports.drop = drop;\nexports.loadSampleFromFile = loadSampleFromFile;\n\nvar _tone = require(\"tone\");\n\nvar _tone2 = _interopRequireDefault(_tone);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /**\n * Sampler\n * @module lib/sampler.js;\n */\n\nvar root = 440;\n\nvar output = void 0;\nvar ready = void 0;\nvar current = \"\";\nvar samples = {};\n\nvar player_count = 12;\n\nfunction load(out, readyCallback) {\n output = out;\n ready = readyCallback;\n document.body.addEventListener(\"dragover\", dragOver);\n document.body.addEventListener(\"drop\", drop);\n}\n\n/**\n * Drag and drop\n */\nfunction dragOver(event) {\n event.preventDefault();\n}\nfunction drop(event) {\n event.preventDefault();\n var files = event.dataTransfer.items ? [].concat(_toConsumableArray(event.dataTransfer.items)).filter(function (item) {\n return item.kind === \"file\";\n }).map(function (item) {\n return item.getAsFile();\n }) : [].concat(_toConsumableArray(event.dataTransfer.files));\n\n var file = files[0];\n var reader = new FileReader();\n\n reader.addEventListener(\"load\", function () {\n return loadSampleFromFile(file, reader.result);\n }, false);\n\n if (file) {\n reader.readAsDataURL(file);\n }\n}\n\nfunction loadSampleFromFile(file, url) {\n var name = file.name;\n\n current = name;\n\n var sample = samples[name] = samples[name] || {};\n sample.root = 440;\n sample.players = [];\n sample.index = -1;\n for (var i = 0; i < player_count; i++) {\n var player = new _tone2.default.Player({\n url: url,\n retrigger: true,\n playbackRate: 1\n });\n player.name = name;\n player.connect(output);\n sample.players.push(player);\n }\n console.log(\"+ Sampler:\", name, \"(\" + sample.players.length + \" voices)\");\n ready();\n}\n\n/**\n * Player\n */\nvar last = [1, 440];\n\nfunction stop() {\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = Object.values(samples)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var sample = _step.value;\n\n sample.players.forEach(function (player) {\n return player.stop();\n });\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n}\nfunction play(interval, root) {\n last = [interval, root];\n var sample = samples[current];\n sample.index = (sample.index + 1) % sample.players.length;\n var player = sample.players[sample.index];\n player.playbackRate = interval * root / sample.root;\n player.start();\n}\n\nfunction pause() {\n // no-op\n}\n\nexports.default = { load: load, play: play, pause: pause, stop: stop };\n\n// for help tuning\n\nfunction keydown(e) {\n // console.log(e.keyCode)\n if (e.metaKey && last && current) {\n var sample = samples[current];\n var step = e.shiftKey ? e.ctrlKey ? 0.1 : 1 : 10;\n switch (e.keyCode) {\n case 38:\n // up\n e.preventDefault();\n sample.root -= step;\n stop();\n play(last[0], last[1]);\n break;\n case 40:\n // down\n e.preventDefault();\n sample.root += step;\n stop();\n play(last[0], last[1]);\n break;\n }\n }\n}\nwindow.addEventListener(\"keydown\", keydown, true);\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/sampler.js\n// module id = 266\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.scales = undefined;\n\nrequire(\"core-js/stable\");\n\nrequire(\"regenerator-runtime/runtime\");\n\nvar _index = require(\"../vendor/number-sequences/dist/index.js\");\n\nvar a = void 0,\n b = void 0; /**\n * Scales\n * @module client/lib/scales.js;\n */\n\nvar scales = exports.scales = [{ name: \"natural\", get: function get(i, j) {\n return [i + 1, j + 1];\n } }, { name: \"undertone\", get: function get(i, j) {\n return [i + 1, i + j + 2];\n } }, { name: \"overtone\", get: function get(i, j) {\n return [i + j + 2, j + 1];\n } }, {\n name: \"primes\",\n reset: function reset(x, y, w, h) {\n a = (0, _index.Prime)().skip(x).take(w).toJS();\n b = (0, _index.Prime)().skip(y).take(h).toJS();\n },\n get: function get(ii, jj, i, j) {\n return [a[i], b[j]];\n }\n}, {\n name: \"arithmetic\",\n reset: function reset(x, y, w, h) {\n a = (0, _index.Arithmetic)(x + 1, x + 1).take(w).toJS();\n b = (0, _index.Arithmetic)(y + 1, y + 1).take(h).toJS();\n console.log(a);\n },\n get: function get(ii, jj, i, j) {\n return [a[i], b[j]];\n }\n},\n// {\n// name: \"triangle\",\n// reset: (x, y, w, h) => {\n// a = Triangle().skip(x).take(w).toJS();\n// b = Triangle().skip(y).take(h).toJS();\n// },\n// get: (ii, jj, i, j) => [a[i], b[j]],\n// },\n{\n name: \"collatz\",\n reset: function reset(x, y, w, h) {\n a = (0, _index.Collatz)(x + 1).take(w).toJS();\n b = (0, _index.Collatz)(y + 1).take(h).toJS();\n },\n get: function get(ii, jj, i, j) {\n return [a[i], b[j]];\n }\n}, {\n name: \"pythagorean\",\n get: function get(i, j) {\n return i < j ? [Math.pow(3, i + 1), Math.pow(2, j + Math.ceil(Math.max(0, i * 1.0 / 2)))] : [Math.pow(2, i + Math.ceil(Math.max(0, j * 1.2 / 2))), Math.pow(3, j)];\n }\n}];\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/lib/scales.js\n// module id = 267\n// module chunks = 0","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/*\n oktransition.add({\n obj: el.style,\n units: \"px\",\n from: { left: 0 },\n to: { left: 100 },\n duration: 1000,\n easing: oktransition.easing.circ_out,\n update: function(obj){\n console.log(obj.left)\n }\n finished: function(){\n console.log(\"done\")\n }\n })\n*/\n\nvar oktransition = {};\nvar transitions = [];\n\nvar last_t = 0;\nvar id = 0;\n\nvar lerp = function lerp(n, a, b) {\n return (b - a) * n + a;\n};\n\noktransition.speed = 1;\noktransition.add = function (transition) {\n transition.id = id++;\n transition.obj = transition.obj || {};\n if (transition.easing) {\n if (typeof transition.easing === \"string\") {\n transition.easing = oktransition.easing[transition.easing];\n }\n } else {\n transition.easing = oktransition.easing.linear;\n }\n if (!(\"from\" in transition) && !(\"to\" in transition)) {\n transition.keys = [];\n } else if (!(\"from\" in transition)) {\n transition.from = {};\n transition.keys = Object.keys(transition.to);\n transition.keys.forEach(function (prop) {\n transition.from[prop] = parseFloat(transition.obj[prop]);\n });\n } else {\n transition.keys = Object.keys(transition.from);\n }\n transition.delay = transition.delay || 0;\n transition.start = last_t + transition.delay;\n transition.done = false;\n transition.after = transition.after || [];\n transition.then = function (fn) {\n transition.after.push(fn);\n return transition;\n };\n transition.tick = 0;\n transition.skip = transition.skip || 1;\n transition.dt = 0;\n transition.cancel = function () {\n return transitions = transitions.filter(function (item) {\n return item !== transition;\n });\n };\n transitions.push(transition);\n return transition;\n};\noktransition.update = function (t) {\n var done = false;\n requestAnimationFrame(oktransition.update);\n last_t = t * oktransition.speed;\n if (transitions.length === 0) return;\n transitions.forEach(function (transition, i) {\n var dt = Math.min(1.0, (t - transition.start) / transition.duration);\n transition.tick++;\n if (dt < 0 || dt < 1 && transition.tick % transition.skip != 0 || transition.done) return;\n var ddt = transition.easing(dt);\n transition.dt = ddt;\n transition.keys.forEach(function (prop) {\n var val = lerp(ddt, transition.from[prop], transition.to[prop]);\n if (transition.round) val = Math.round(val);\n if (transition.units) val = Math.round(val) + transition.units;\n transition.obj[prop] = val;\n });\n if (transition.update) {\n transition.update(transition.obj, dt);\n }\n if (dt === 1) {\n if (transition.finished) {\n transition.finished(transition);\n }\n if (transition.after.length) {\n var twn = transition.after.shift();\n twn.obj = twn.obj || transition.obj;\n twn.after = transition.after;\n oktransition.add(twn);\n }\n if (transition.loop) {\n transition.start = t + transition.delay;\n } else {\n done = true;\n transition.done = true;\n }\n }\n });\n if (done) {\n transitions = transitions.filter(function (transition) {\n return !transition.done;\n });\n }\n};\n\nrequestAnimationFrame(oktransition.update);\n\noktransition.easing = {\n linear: function linear(t) {\n return t;\n },\n circ_out: function circ_out(t) {\n return Math.sqrt(1 - (t = t - 1) * t);\n },\n circ_in: function circ_in(t) {\n return -(Math.sqrt(1 - t * t) - 1);\n },\n circ_in_out: function circ_in_out(t) {\n return (t *= 2) < 1 ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1);\n },\n quad_in: function quad_in(n) {\n return Math.pow(n, 2);\n },\n quad_out: function quad_out(n) {\n return n * (n - 2) * -1;\n },\n quad_in_out: function quad_in_out(n) {\n n = n * 2;\n if (n < 1) {\n return Math.pow(n, 2) / 2;\n }\n return -1 * (--n * (n - 2) - 1) / 2;\n },\n cubic_bezier: function cubic_bezier(mX1, mY1, mX2, mY2) {\n function A(aA1, aA2) {\n return 1.0 - 3.0 * aA2 + 3.0 * aA1;\n }\n function B(aA1, aA2) {\n return 3.0 * aA2 - 6.0 * aA1;\n }\n function C(aA1) {\n return 3.0 * aA1;\n }\n\n // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.\n function CalcBezier(aT, aA1, aA2) {\n return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;\n }\n\n // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.\n function GetSlope(aT, aA1, aA2) {\n return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);\n }\n\n function GetTForX(aX) {\n // Newton raphson iteration\n var aGuessT = aX;\n for (var i = 0; i < 10; ++i) {\n var currentSlope = GetSlope(aGuessT, mX1, mX2);\n if (currentSlope == 0.0) return aGuessT;\n var currentX = CalcBezier(aGuessT, mX1, mX2) - aX;\n aGuessT -= currentX / currentSlope;\n }\n return aGuessT;\n }\n\n return function (aX) {\n if (mX1 == mY1 && mX2 == mY2) return aX; // linear\n return CalcBezier(aX, mY1, mY2);\n };\n }\n};\n\nexports.default = oktransition;\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./client/vendor/oktransition.js\n// module id = 268\n// module chunks = 0","'use strict';\n\n// MODULES //\n\nvar isArray = require( 'validate.io-array' ),\n\tisIntegerArray = require( 'validate.io-integer-array' ),\n\tisFunction = require( 'validate.io-function' );\n\n\n// VARIABLES //\n\nvar MAXINT = Math.pow( 2, 31 ) - 1;\n\n\n// FUNCTIONS //\n\n/**\n* FUNCTION: gcd( a, b )\n*\tComputes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm.\n*\n* @param {Number} a - integer\n* @param {Number} b - integer\n* @returns {Number} greatest common divisor\n*/\nfunction gcd( a, b ) {\n\tvar k = 1,\n\t\tt;\n\t// Simple cases:\n\tif ( a === 0 ) {\n\t\treturn b;\n\t}\n\tif ( b === 0 ) {\n\t\treturn a;\n\t}\n\t// Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...\n\twhile ( a%2 === 0 && b%2 === 0 ) {\n\t\ta = a / 2; // right shift\n\t\tb = b / 2; // right shift\n\t\tk = k * 2; // left shift\n\t}\n\t// Reduce `a` to an odd number...\n\twhile ( a%2 === 0 ) {\n\t\ta = a / 2; // right shift\n\t}\n\t// Henceforth, `a` is always odd...\n\twhile ( b ) {\n\t\t// Remove all factors of 2 in `b`, as they are not common...\n\t\twhile ( b%2 === 0 ) {\n\t\t\tb = b / 2; // right shift\n\t\t}\n\t\t// `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...\n\t\tif ( a > b ) {\n\t\t\tt = b;\n\t\t\tb = a;\n\t\t\ta = t;\n\t\t}\n\t\tb = b - a; // b=0 iff b=a\n\t}\n\t// Restore common factors of 2...\n\treturn k * a;\n} // end FUNCTION gcd()\n\n/**\n* FUNCTION: bitwise( a, b )\n*\tComputes the greatest common divisor of two integers `a` and `b`, using the binary GCD algorithm and bitwise operations.\n*\n* @param {Number} a - safe integer\n* @param {Number} b - safe integer\n* @returns {Number} greatest common divisor\n*/\nfunction bitwise( a, b ) {\n\tvar k = 0,\n\t\tt;\n\t// Simple cases:\n\tif ( a === 0 ) {\n\t\treturn b;\n\t}\n\tif ( b === 0 ) {\n\t\treturn a;\n\t}\n\t// Reduce `a` and/or `b` to odd numbers and keep track of the greatest power of 2 dividing both `a` and `b`...\n\twhile ( (a & 1) === 0 && (b & 1) === 0 ) {\n\t\ta >>>= 1; // right shift\n\t\tb >>>= 1; // right shift\n\t\tk++;\n\t}\n\t// Reduce `a` to an odd number...\n\twhile ( (a & 1) === 0 ) {\n\t\ta >>>= 1; // right shift\n\t}\n\t// Henceforth, `a` is always odd...\n\twhile ( b ) {\n\t\t// Remove all factors of 2 in `b`, as they are not common...\n\t\twhile ( (b & 1) === 0 ) {\n\t\t\tb >>>= 1; // right shift\n\t\t}\n\t\t// `a` and `b` are both odd. Swap values such that `b` is the larger of the two values, and then set `b` to the difference (which is even)...\n\t\tif ( a > b ) {\n\t\t\tt = b;\n\t\t\tb = a;\n\t\t\ta = t;\n\t\t}\n\t\tb = b - a; // b=0 iff b=a\n\t}\n\t// Restore common factors of 2...\n\treturn a << k;\n} // end FUNCTION bitwise()\n\n\n// GREATEST COMMON DIVISOR //\n\n/**\n* FUNCTION: compute( arr[, clbk] )\n*\tComputes the greatest common divisor.\n*\n* @param {Number[]|Number} arr - input array of integers\n* @param {Function|Number} [clbk] - accessor function for accessing array values\n* @returns {Number|Null} greatest common divisor or null\n*/\nfunction compute() {\n\tvar nargs = arguments.length,\n\t\targs,\n\t\tclbk,\n\t\tarr,\n\t\tlen,\n\t\ta, b,\n\t\ti;\n\n\t// Copy the input arguments to an array...\n\targs = new Array( nargs );\n\tfor ( i = 0; i < nargs; i++ ) {\n\t\targs[ i ] = arguments[ i ];\n\t}\n\t// Have we been provided with integer arguments?\n\tif ( isIntegerArray( args ) ) {\n\t\tif ( nargs === 2 ) {\n\t\t\ta = args[ 0 ];\n\t\t\tb = args[ 1 ];\n\t\t\tif ( a < 0 ) {\n\t\t\t\ta = -a;\n\t\t\t}\n\t\t\tif ( b < 0 ) {\n\t\t\t\tb = -b;\n\t\t\t}\n\t\t\tif ( a <= MAXINT && b <= MAXINT ) {\n\t\t\t\treturn bitwise( a, b );\n\t\t\t} else {\n\t\t\t\treturn gcd( a, b );\n\t\t\t}\n\t\t}\n\t\tarr = args;\n\t}\n\t// If not integers, ensure the first argument is an array...\n\telse if ( !isArray( args[ 0 ] ) ) {\n\t\tthrow new TypeError( 'gcd()::invalid input argument. Must provide an array of integers. Value: `' + args[ 0 ] + '`.' );\n\t}\n\t// Have we been provided with more than one argument? If so, ensure that the accessor argument is a function...\n\telse if ( nargs > 1 ) {\n\t\tarr = args[ 0 ];\n\t\tclbk = args[ 1 ];\n\t\tif ( !isFunction( clbk ) ) {\n\t\t\tthrow new TypeError( 'gcd()::invalid input argument. Accessor must be a function. Value: `' + clbk + '`.' );\n\t\t}\n\t}\n\t// We have been provided an array...\n\telse {\n\t\tarr = args[ 0 ];\n\t}\n\tlen = arr.length;\n\n\t// Check if a sufficient number of values have been provided...\n\tif ( len < 2 ) {\n\t\treturn null;\n\t}\n\t// If an accessor is provided, extract the array values...\n\tif ( clbk ) {\n\t\ta = new Array( len );\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\ta[ i ] = clbk( arr[ i ], i );\n\t\t}\n\t\tarr = a;\n\t}\n\t// Given an input array, ensure all array values are integers...\n\tif ( nargs < 3 ) {\n\t\tif ( !isIntegerArray( arr ) ) {\n\t\t\tthrow new TypeError( 'gcd()::invalid input argument. Accessed array values must be integers. Value: `' + arr + '`.' );\n\t\t}\n\t}\n\t// Convert any negative integers to positive integers...\n\tfor ( i = 0; i < len; i++ ) {\n\t\ta = arr[ i ];\n\t\tif ( a < 0 ) {\n\t\t\tarr[ i ] = -a;\n\t\t}\n\t}\n\t// Exploit the fact that the gcd is an associative function...\n\ta = arr[ 0 ];\n\tfor ( i = 1; i < len; i++ ) {\n\t\tb = arr[ i ];\n\t\tif ( b <= MAXINT && a <= MAXINT ) {\n\t\t\ta = bitwise( a, b );\n\t\t} else {\n\t\t\ta = gcd( a, b );\n\t\t}\n\t}\n\treturn a;\n} // end FUNCTION compute()\n\n\n// EXPORTS //\n\nmodule.exports = compute;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/compute-gcd/lib/index.js\n// module id = 269\n// module chunks = 0","\"use strict\";\n\nvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }(); /**\n * Lambdoma Triangle\n * @module index.js;\n */\n\nvar _computeGcd = require(\"compute-gcd\");\n\nvar _computeGcd2 = _interopRequireDefault(_computeGcd);\n\nvar _keys = require(\"./lib/keys\");\n\nvar _keys2 = _interopRequireDefault(_keys);\n\nvar _color = require(\"./lib/color\");\n\nvar _color2 = _interopRequireDefault(_color);\n\nvar _kalimba = require(\"./lib/kalimba\");\n\nvar _kalimba2 = _interopRequireDefault(_kalimba);\n\nvar _sampler = require(\"./lib/sampler\");\n\nvar _sampler2 = _interopRequireDefault(_sampler);\n\nvar _organ = require(\"./lib/organ\");\n\nvar _organ2 = _interopRequireDefault(_organ);\n\nvar _midi = require(\"./lib/midi\");\n\nvar _midi2 = _interopRequireDefault(_midi);\n\nvar _oktransition = require(\"./vendor/oktransition\");\n\nvar _oktransition2 = _interopRequireDefault(_oktransition);\n\nvar _output = require(\"./lib/output\");\n\nvar _util = require(\"./lib/util\");\n\nvar _scales = require(\"./lib/scales\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar instrument = _kalimba2.default;\n\nvar grid = document.createElement(\"grid\");\nvar root = 440;\nvar s = 50;\nvar w = void 0,\n h = void 0,\n ws = void 0,\n hs = void 0;\n\nvar add_on = 0;\nvar mul_on = 1.0;\nvar add_off = 0.1;\nvar mul_off = 0.9;\n\nvar dragging = false;\nvar erasing = false;\nvar lastNote = 0;\nvar notes = [];\nvar base_x = 0;\nvar base_y = 0;\nvar scaleMode = 0;\nvar is_split = false;\nvar intervals = void 0;\n\n(0, _util.requestAudioContext)(function () {\n var output = (0, _output.getOutput)();\n document.body.appendChild(grid);\n _kalimba2.default.load(output);\n _organ2.default.load(output);\n _sampler2.default.load(output, function ready() {\n instrument = _sampler2.default;\n });\n build();\n bind();\n});\n\nfunction build() {\n w = window.innerWidth;\n h = window.innerHeight;\n ws = Math.ceil(w / s);\n hs = Math.ceil(h / s);\n var scale = _scales.scales[scaleMode % _scales.scales.length];\n if (scale.reset) {\n scale.reset(Math.round(base_x), Math.round(base_y), ws, hs);\n }\n for (var i = 0; i < ws; i++) {\n notes[i] = [];\n for (var j = 0; j < hs; j++) {\n notes[i][j] = add(i, j);\n }\n }\n log();\n}\nfunction rebuild() {\n notes.forEach(function (row) {\n return row.forEach(function (note) {\n return note.destroy();\n });\n });\n build();\n}\nfunction log() {\n var seen = {};\n // console.log(notes);\n for (var i = 0; i < 8; i++) {\n for (var j = 0; j < 8; j++) {\n var interval = notes[i][j].interval;\n var rounded = (0, _util.roundInterval)(interval);\n if (!seen[rounded] && (0, _util.intervalInRange)(interval, root)) {\n seen[rounded] = notes[i][j].interval;\n }\n }\n }\n intervals = Object.values(seen).sort(function (a, b) {\n return a - b;\n });\n // console.log(intervals);\n console.log(intervals.length, \"unique intervals in 8x8\");\n}\nfunction play(note) {\n if (!_organ2.default.isPlaying(note.interval)) {\n var interval = note.interval;\n // while (interval < root) {\n // interval *= 2;\n // }\n // while (interval > root) {\n // interval /= 2;\n // }\n var rounded = (0, _util.roundInterval)(note.interval);\n _organ2.default.play(interval);\n notes.forEach(function (row) {\n return row.forEach(function (note) {\n return note.rounded === rounded && note.div.classList.add(\"playing\");\n });\n });\n }\n}\nfunction trigger(note) {\n if ((0, _util.intervalInRange)(note.interval, root)) {\n instrument.play(note.interval, root);\n }\n}\nfunction trigger_index(index) {\n var interval = intervals[index];\n if (interval) {\n instrument.play(interval, root);\n }\n}\nfunction pause(note) {\n _organ2.default.pause(note.interval);\n var rounded = (0, _util.roundInterval)(note.interval);\n notes.forEach(function (row) {\n return row.forEach(function (note) {\n return note.rounded === rounded && note.div.classList.remove(\"playing\");\n });\n });\n}\nfunction toggle(note) {\n if (_organ2.default.isPlaying(note.rounded) || note.div.classList.contains(\"playing\")) {\n pause(note);\n } else {\n play(note);\n }\n}\n\nfunction add(i, j) {\n var ii = i + Math.round(base_x);\n var jj = j + Math.round(base_y);\n\n var scale = _scales.scales[scaleMode % _scales.scales.length];\n\n var _scale$get = scale.get(ii, jj, i, j, Math.round(base_x), Math.round(base_y)),\n _scale$get2 = _slicedToArray(_scale$get, 2),\n a = _scale$get2[0],\n b = _scale$get2[1];\n\n var div = document.createElement(\"div\");\n var interval = a / b;\n // const interval = root * Math.pow(2, ((b / a) % 1) + 1);\n var add = 0;\n var frac = void 0;\n div.style.left = i * s + \"px\";\n div.style.top = j * s + \"px\";\n\n var note = {\n interval: interval,\n rounded: (0, _util.roundInterval)(interval, root),\n div: div,\n i: i,\n j: j,\n playing: false,\n destroy: function destroy() {\n div.parentNode && div.parentNode.removeChild(div);\n },\n recolor: function recolor(numerator, denominator) {\n var aa = a / numerator;\n var bb = b / denominator;\n if (aa < bb) {\n add = -Math.log(bb / aa) / 3.5;\n } else {\n add = Math.log(aa / bb) / 6;\n }\n var a_inv = a * denominator;\n var b_inv = b * numerator;\n var ba_gcd = (0, _computeGcd2.default)(a_inv, b_inv);\n var a_disp = a_inv / ba_gcd;\n var b_disp = b_inv / ba_gcd;\n\n frac = Math.log2(aa / bb) % 1;\n var frac_orig = Math.log2(a / b) % 1;\n if (frac < 0) {\n frac += 1;\n }\n if (frac_orig < 0) {\n frac += 1;\n }\n if (frac_orig === 0) {\n div.style.fontWeight = \"900\";\n } else {\n div.style.fontWeight = \"500\";\n }\n\n div.innerHTML = \"
- The rows display the overtone series (1/1, 2/1, 3/1 ...), while - the undertone series (1/1, 1/2, 1/3, ...) is shown by the - columns. The resulting intervals are instantly musically meaningful, - though they arise from simple ratios. + The rows display the overtone series (1/1, 2/1, 3/1 ...). The + columns multiply out the undertone series (1/1, 1/2, 1/3, ...). + The resulting intervals are instantly musically meaningful, though + they arise from simple ratios.
Brightness indicates octave. Color indicates position in -- cgit v1.2.3-70-g09d2