2014-12-01 04:26:06 +00:00
|
|
|
define(["Tone/core/Tone", "Tone/signal/SignalBase"], function(Tone){
|
2014-11-30 18:16:20 +00:00
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @class Wraps the WaveShaperNode
|
|
|
|
*
|
2014-12-01 04:26:06 +00:00
|
|
|
* @extends {Tone.SignalBase}
|
2014-11-30 18:16:20 +00:00
|
|
|
* @constructor
|
|
|
|
* @param {function(number, number)|Array|number} mapping the function used to define the values.
|
|
|
|
* The mapping function should take two arguments:
|
|
|
|
* the first is the value at the current position
|
|
|
|
* and the second is the array position.
|
|
|
|
* If the argument is an array, that array will be
|
|
|
|
* set as the wave shapping function
|
|
|
|
* @param {number} [bufferLen=1024] the length of the WaveShaperNode buffer.
|
2015-02-27 18:40:35 +00:00
|
|
|
* @example
|
2015-06-14 05:17:09 +00:00
|
|
|
* var timesTwo = new Tone.WaveShaper(function(val){
|
|
|
|
* return val * 2;
|
|
|
|
* }, 2048);
|
2014-11-30 18:16:20 +00:00
|
|
|
*/
|
|
|
|
Tone.WaveShaper = function(mapping, bufferLen){
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the waveshaper
|
|
|
|
* @type {WaveShaperNode}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._shaper = this.input = this.output = this.context.createWaveShaper();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the waveshapers curve
|
|
|
|
* @type {Float32Array}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._curve = null;
|
|
|
|
|
|
|
|
if (Array.isArray(mapping)){
|
2015-02-06 22:47:26 +00:00
|
|
|
this.curve = mapping;
|
2014-11-30 18:16:20 +00:00
|
|
|
} else if (isFinite(mapping) || this.isUndef(mapping)){
|
|
|
|
this._curve = new Float32Array(this.defaultArg(mapping, 1024));
|
2015-02-02 14:41:32 +00:00
|
|
|
} else if (this.isFunction(mapping)){
|
2014-11-30 18:16:20 +00:00
|
|
|
this._curve = new Float32Array(this.defaultArg(bufferLen, 1024));
|
|
|
|
this.setMap(mapping);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-12-01 04:26:06 +00:00
|
|
|
Tone.extend(Tone.WaveShaper, Tone.SignalBase);
|
2014-11-30 18:16:20 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* uses a mapping function to set the value of the curve
|
|
|
|
* @param {function(number, number)} mapping the function used to define the values.
|
|
|
|
* The mapping function should take two arguments:
|
|
|
|
* the first is the value at the current position
|
|
|
|
* and the second is the array position
|
2015-06-14 00:54:29 +00:00
|
|
|
* @returns {Tone.WaveShaper} this
|
2014-11-30 18:16:20 +00:00
|
|
|
*/
|
|
|
|
Tone.WaveShaper.prototype.setMap = function(mapping){
|
|
|
|
for (var i = 0, len = this._curve.length; i < len; i++){
|
|
|
|
var normalized = (i / (len)) * 2 - 1;
|
2015-02-27 18:40:35 +00:00
|
|
|
this._curve[i] = mapping(normalized, i);
|
2014-11-30 18:16:20 +00:00
|
|
|
}
|
|
|
|
this._shaper.curve = this._curve;
|
2015-02-02 03:56:33 +00:00
|
|
|
return this;
|
2014-11-30 18:16:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2015-02-06 22:47:26 +00:00
|
|
|
* The array to set as the waveshaper curve
|
|
|
|
* @memberOf Tone.WaveShaper#
|
|
|
|
* @type {Array}
|
|
|
|
* @name curve
|
2014-11-30 18:16:20 +00:00
|
|
|
*/
|
2015-02-06 22:47:26 +00:00
|
|
|
Object.defineProperty(Tone.WaveShaper.prototype, "curve", {
|
|
|
|
get : function(){
|
|
|
|
return this._shaper.curve;
|
|
|
|
},
|
|
|
|
set : function(mapping){
|
|
|
|
//fixes safari WaveShaperNode bug
|
|
|
|
if (this._isSafari()){
|
|
|
|
var first = mapping[0];
|
|
|
|
mapping.unshift(first);
|
|
|
|
}
|
|
|
|
this._curve = new Float32Array(mapping);
|
|
|
|
this._shaper.curve = this._curve;
|
2014-11-30 18:16:20 +00:00
|
|
|
}
|
2015-02-06 22:47:26 +00:00
|
|
|
});
|
2014-11-30 18:16:20 +00:00
|
|
|
|
|
|
|
/**
|
2015-02-06 22:47:26 +00:00
|
|
|
* The oversampling. Can either be "none", "2x" or "4x"
|
|
|
|
* @memberOf Tone.WaveShaper#
|
|
|
|
* @type {string}
|
2015-03-07 19:17:16 +00:00
|
|
|
* @name oversample
|
2014-11-30 18:16:20 +00:00
|
|
|
*/
|
2015-02-06 22:47:26 +00:00
|
|
|
Object.defineProperty(Tone.WaveShaper.prototype, "oversample", {
|
|
|
|
get : function(){
|
|
|
|
return this._shaper.oversample;
|
|
|
|
},
|
|
|
|
set : function(oversampling){
|
|
|
|
this._shaper.oversample = oversampling;
|
|
|
|
}
|
|
|
|
});
|
2014-11-30 18:16:20 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* returns true if the browser is safari
|
|
|
|
* @return {boolean}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
Tone.WaveShaper.prototype._isSafari = function(){
|
|
|
|
var ua = navigator.userAgent.toLowerCase();
|
|
|
|
return ua.indexOf("safari") !== -1 && ua.indexOf("chrome") === -1;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* clean up
|
2015-06-14 00:54:29 +00:00
|
|
|
* @returns {Tone.WaveShaper} this
|
2014-11-30 18:16:20 +00:00
|
|
|
*/
|
|
|
|
Tone.WaveShaper.prototype.dispose = function(){
|
|
|
|
Tone.prototype.dispose.call(this);
|
|
|
|
this._shaper.disconnect();
|
|
|
|
this._shaper = null;
|
|
|
|
this._curve = null;
|
2015-02-02 03:56:33 +00:00
|
|
|
return this;
|
2014-11-30 18:16:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
return Tone.WaveShaper;
|
|
|
|
});
|