import Tone from "../core/Tone"; import "../effect/Effect"; import "../signal/WaveShaper"; /** * @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 = Tone.defaults(arguments, ["order"], Tone.Chebyshev); 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; }; export default Tone.Chebyshev;