import Tone from "../core/Tone"; import "../type/Type"; /** * @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 = Tone.defaults(arguments, ["values", "index"], Tone.CtrlInterpolate); Tone.call(this); /** * 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 (Tone.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 (Tone.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 (Tone.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; }; export default Tone.CtrlInterpolate;