Tone.js/Tone/signal/WaveShaper.js

142 lines
4.4 KiB
JavaScript
Raw Normal View History

define(["Tone/core/Tone", "Tone/signal/SignalBase"], function(Tone){
"use strict";
/**
2015-07-04 19:25:37 +00:00
* @class Wraps the native Web Audio API
* [WaveShaperNode](http://webaudio.github.io/web-audio-api/#the-waveshapernode-interface).
*
* @extends {Tone.SignalBase}
* @constructor
2015-06-20 19:50:57 +00:00
* @param {function|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
2015-06-19 04:52:04 +00:00
* set as the wave shaping function. The input
* signal is an AudioRange [-1, 1] value and the output
2015-06-20 19:50:57 +00:00
* signal can take on any numerical values.
2015-06-19 04:52:04 +00:00
*
2015-06-20 19:50:57 +00:00
* @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);
2015-06-20 19:50:57 +00:00
* @example
* //a waveshaper can also be constructed with an array of values
* var invert = new Tone.WaveShaper([1, -1]);
*/
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)){
this.curve = mapping;
} 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)){
this._curve = new Float32Array(this.defaultArg(bufferLen, 1024));
this.setMap(mapping);
}
};
Tone.extend(Tone.WaveShaper, Tone.SignalBase);
/**
2015-06-19 04:52:04 +00:00
* Uses a mapping function to set the value of the curve.
* @param {function} mapping The function used to define the values.
* The mapping function take two arguments:
* the first is the value at the current position
* which goes from -1 to 1 over the number of elements
* in the curve array. The second argument is the array position.
* @returns {Tone.WaveShaper} this
2015-06-19 04:52:04 +00:00
* @example
* //map the input signal from [-1, 1] to [0, 10]
* shaper.setMap(function(val, index){
* return (val + 1) * 5;
* })
*/
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);
}
this._shaper.curve = this._curve;
2015-02-02 03:56:33 +00:00
return this;
};
/**
2015-06-19 04:52:04 +00:00
* The array to set as the waveshaper curve. For linear curves
* array length does not make much difference, but for complex curves
* longer arrays will provide smoother interpolation.
* @memberOf Tone.WaveShaper#
* @type {Array}
* @name curve
*/
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;
}
});
/**
2015-06-19 04:52:04 +00:00
* Specifies what type of oversampling (if any) should be used when
* applying the shaping curve. Can either be "none", "2x" or "4x".
* @memberOf Tone.WaveShaper#
* @type {string}
* @name oversample
*/
Object.defineProperty(Tone.WaveShaper.prototype, "oversample", {
get : function(){
return this._shaper.oversample;
},
set : function(oversampling){
this._shaper.oversample = oversampling;
}
});
/**
* 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;
};
/**
2015-06-19 04:52:04 +00:00
* Clean up.
* @returns {Tone.WaveShaper} this
*/
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;
};
return Tone.WaveShaper;
});