2014-11-30 18:20:35 +00:00
|
|
|
define(["Tone/core/Tone", "Tone/effect/Effect", "Tone/signal/WaveShaper"], function(Tone){
|
2014-10-19 23:39:50 +00:00
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @class A Chebyshev waveshaper. Good for making different types of distortion sounds.
|
|
|
|
* Note that odd orders sound very different from even ones. order = 1 is no change.
|
|
|
|
* http://music.columbia.edu/cmc/musicandcomputers/chapter4/04_06.php
|
|
|
|
*
|
|
|
|
* @extends {Tone.Effect}
|
|
|
|
* @constructor
|
|
|
|
* @param {number} order the order of the chebyshev polynomial
|
|
|
|
*/
|
|
|
|
Tone.Chebyshev = function(){
|
|
|
|
|
|
|
|
var options = this.optionsObject(arguments, ["order"], Tone.Chebyshev.defaults);
|
|
|
|
Tone.Effect.call(this);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @type {WaveShaperNode}
|
|
|
|
* @private
|
|
|
|
*/
|
2014-11-30 18:20:35 +00:00
|
|
|
this._shaper = new Tone.WaveShaper(4096);
|
2014-11-04 00:22:17 +00:00
|
|
|
|
2014-10-19 23:39:50 +00:00
|
|
|
this.connectEffect(this._shaper);
|
|
|
|
this.setOrder(options.order);
|
|
|
|
this.setOversample(options.oversample);
|
|
|
|
};
|
|
|
|
|
|
|
|
Tone.extend(Tone.Chebyshev, Tone.Effect);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @static
|
|
|
|
* @const
|
|
|
|
* @type {Object}
|
|
|
|
*/
|
|
|
|
Tone.Chebyshev.defaults = {
|
|
|
|
"order" : 1,
|
|
|
|
"oversample" : "none"
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set the order of the Chebyshev polynomial i.e.
|
|
|
|
* order = 2 -> 2x^2 + 1
|
|
|
|
* order = 3 -> 4x^3 + 3x
|
|
|
|
* @param {number} order the order of the Chebyshev nominal range of 1 - 100
|
|
|
|
*/
|
|
|
|
Tone.Chebyshev.prototype.setOrder = function(order) {
|
2014-11-30 18:20:35 +00:00
|
|
|
var curve = new Array(4096);
|
|
|
|
var len = curve.length;
|
2014-10-19 23:39:50 +00:00
|
|
|
for (var i = 0; i < len; ++i) {
|
|
|
|
var x = i * 2 / len - 1;
|
|
|
|
if (x === 0){
|
|
|
|
//should output 0 when input is 0
|
2014-11-30 18:20:35 +00:00
|
|
|
curve[i] = 0;
|
2014-10-19 23:39:50 +00:00
|
|
|
} else {
|
2014-11-30 18:20:35 +00:00
|
|
|
curve[i] = this._getCoefficient(x, order, {});
|
2014-10-19 23:39:50 +00:00
|
|
|
}
|
|
|
|
}
|
2014-11-30 18:20:35 +00:00
|
|
|
this._shaper.setCurve(curve);
|
2014-10-19 23:39:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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];
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set the oversampling
|
|
|
|
* @param {string} oversampling can either be "none", "2x" or "4x"
|
|
|
|
*/
|
|
|
|
Tone.Chebyshev.prototype.setOversample = function(oversampling) {
|
2014-11-30 18:20:35 +00:00
|
|
|
this._shaper.setOversample(oversampling);
|
2014-10-19 23:39:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* clean up
|
|
|
|
*/
|
|
|
|
Tone.Chebyshev.prototype.dispose = function(){
|
|
|
|
Tone.Effect.prototype.dispose.call(this);
|
2014-11-30 18:20:35 +00:00
|
|
|
this._shaper.dispose();
|
2014-10-19 23:39:50 +00:00
|
|
|
this._shaper = null;
|
|
|
|
};
|
|
|
|
|
|
|
|
return Tone.Chebyshev;
|
|
|
|
});
|