Tone.js/Tone/signal/Inverse.js
2014-11-30 13:20:35 -05:00

144 lines
No EOL
3.4 KiB
JavaScript

define(["Tone/core/Tone", "Tone/signal/Subtract", "Tone/signal/Multiply", "Tone/signal/WaveShaper"],
function(Tone){
"use strict";
/**
* this is the maximum value that the divide can handle
* @type {number}
* @const
*/
var MAX_VALUE = Math.pow(2, 13);
/**
* @private
* @static
* @type {Array}
*/
var guessCurve = new Array(MAX_VALUE);
//set the value
for (var i = 0; i < guessCurve.length; i++){
var normalized = (i / (guessCurve.length - 1)) * 2 - 1;
if (normalized === 0){
guessCurve[i] = 0;
} else {
guessCurve[i] = 1 / (normalized * MAX_VALUE);
}
}
/**
* @class Compute the inverse of the input.
* Uses this approximation algorithm:
* http://en.wikipedia.org/wiki/Multiplicative_inverse#Algorithms
*
* @extends {Tone}
* @constructor
* @param {number} [precision=3] the precision of the calculation
*/
Tone.Inverse = function(precision){
Tone.call(this);
precision = this.defaultArg(precision, 3);
/**
* a constant generator of the value 2
* @private
* @type {Tone.Signal}
*/
this._two = new Tone.Signal(2);
/**
* starting guess is 0.1 times the input
* @type {Tone.Multiply}
* @private
*/
this._guessMult = new Tone.Multiply(1/MAX_VALUE);
/**
* produces a starting guess based on the input
* @type {WaveShaperNode}
* @private
*/
this._guess = new Tone.WaveShaper(guessCurve);
this.chain(this.input, this._guessMult, this._guess);
/**
* the array of inverse helpers
* @type {Array}
* @private
*/
this._inverses = new Array(precision);
//create the helpers
for (var i = 0; i < precision; i++){
var guess;
if (i === 0){
guess = this._guess;
} else {
guess = this._inverses[i-1];
}
var inv = new InverseHelper(guess, this._two);
this.input.connect(inv);
this._inverses[i] = inv;
}
this._inverses[precision-1].connect(this.output);
};
Tone.extend(Tone.Inverse);
/**
* clean up
*/
Tone.Inverse.prototype.dispose = function(){
Tone.prototype.dispose.call(this);
for (var i = 0; i < this._inverses.length; i++){
this._inverses[i].dispose();
this._inverses[i] = null;
}
this._inverses = null;
this._two.dispose();
this._two = null;
this._guessMult.dispose();
this._guessMult = null;
this._guess.disconnect();
this._guess = null;
};
// BEGIN INVERSE HELPER ///////////////////////////////////////////////////
/**
* internal helper function for computing the inverse of a signal
* @extends {Tone}
* @constructor
* @internal
*/
var InverseHelper = function(guess, two){
this._outerMultiply = new Tone.Multiply();
this._innerMultiply = new Tone.Multiply();
this._subtract = new Tone.Subtract();
//connections
guess.connect(this._innerMultiply, 0, 1);
two.connect(this._subtract, 0, 0);
this._innerMultiply.connect(this._subtract, 0, 1);
this._subtract.connect(this._outerMultiply, 0, 1);
guess.connect(this._outerMultiply, 0, 0);
this.output = this._outerMultiply;
this.input = this._innerMultiply;
};
Tone.extend(InverseHelper);
InverseHelper.prototype.dispose = function(){
this._outerMultiply.dispose();
this._outerMultiply = null;
this._innerMultiply.dispose();
this._innerMultiply = null;
this._subtract.dispose();
this._subtract = null;
};
// END INVERSE HELPER /////////////////////////////////////////////////////
return Tone.Inverse;
});