mirror of
https://github.com/Tonejs/Tone.js
synced 2025-01-03 23:48:43 +00:00
140 lines
3.6 KiB
JavaScript
140 lines
3.6 KiB
JavaScript
|
define(["Tone/core/Tone", "Tone/core/Type"], function (Tone) {
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
/**
|
||
|
* @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([
|
||
|
* ["C3", "G4", "E5"],
|
||
|
* ["D4", "F#4", "E5"],
|
||
|
* ]);
|
||
|
* @param {Array} values The array of values to interpolate over
|
||
|
* @param {Positive} index The initial interpolation index.
|
||
|
*/
|
||
|
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;
|
||
|
|
||
|
/**
|
||
|
* Use an exponent to ease between values.
|
||
|
* @type {Positive}
|
||
|
*/
|
||
|
this.exponent = options.exponent;
|
||
|
};
|
||
|
|
||
|
Tone.extend(Tone.CtrlInterpolate);
|
||
|
|
||
|
/**
|
||
|
* The defaults
|
||
|
* @const
|
||
|
* @type {Object}
|
||
|
*/
|
||
|
Tone.CtrlInterpolate.defaults = {
|
||
|
"index" : 0,
|
||
|
"exponent" : 1,
|
||
|
"values" : []
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The current interpolated value based on the index and exponent
|
||
|
* @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);
|
||
|
index = Math.pow(index, this.exponent);
|
||
|
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 if (this.isNote(val)){
|
||
|
return this.toFrequency(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;
|
||
|
});
|