2014-11-30 18:20:35 +00:00
|
|
|
define(["Tone/core/Tone", "Tone/signal/Abs", "Tone/signal/Subtract",
|
|
|
|
"Tone/signal/Multiply", "Tone/signal/Signal", "Tone/signal/WaveShaper"],
|
2014-08-29 20:36:52 +00:00
|
|
|
function(Tone){
|
2014-06-30 15:34:52 +00:00
|
|
|
|
2014-09-04 04:41:40 +00:00
|
|
|
"use strict";
|
|
|
|
|
2014-06-30 15:34:52 +00:00
|
|
|
/**
|
2014-08-23 17:48:52 +00:00
|
|
|
* @class Follow the envelope of the incoming signal.
|
|
|
|
* Careful with small (< 0.02) attack or decay values.
|
|
|
|
* The follower has some ripple which gets exaggerated
|
|
|
|
* by small values.
|
2014-07-22 23:17:45 +00:00
|
|
|
*
|
2014-06-30 15:34:52 +00:00
|
|
|
* @constructor
|
|
|
|
* @extends {Tone}
|
2014-12-02 06:42:08 +00:00
|
|
|
* @param {Tone.Time} [attack = 0.05]
|
|
|
|
* @param {Tone.Time} [release = 0.5]
|
2014-06-30 15:34:52 +00:00
|
|
|
*/
|
2014-08-24 23:28:42 +00:00
|
|
|
Tone.Follower = function(){
|
2014-08-23 17:48:52 +00:00
|
|
|
|
2014-07-02 22:20:34 +00:00
|
|
|
Tone.call(this);
|
2014-08-25 14:23:37 +00:00
|
|
|
var options = this.optionsObject(arguments, ["attack", "release"], Tone.Follower.defaults);
|
2014-07-02 22:20:34 +00:00
|
|
|
|
2014-06-30 15:34:52 +00:00
|
|
|
/**
|
2014-07-02 22:20:34 +00:00
|
|
|
* @type {Tone.Abs}
|
2014-06-30 15:34:52 +00:00
|
|
|
* @private
|
|
|
|
*/
|
2014-07-02 22:20:34 +00:00
|
|
|
this._abs = new Tone.Abs();
|
2014-06-30 15:34:52 +00:00
|
|
|
|
|
|
|
/**
|
2014-07-23 19:22:46 +00:00
|
|
|
* the lowpass filter which smooths the input
|
2014-06-30 15:34:52 +00:00
|
|
|
* @type {BiquadFilterNode}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._filter = this.context.createBiquadFilter();
|
|
|
|
this._filter.type = "lowpass";
|
2014-08-23 17:48:52 +00:00
|
|
|
this._filter.frequency.value = 0;
|
|
|
|
this._filter.Q.value = -100;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @type {WaveShaperNode}
|
|
|
|
* @private
|
|
|
|
*/
|
2014-11-30 18:20:35 +00:00
|
|
|
this._frequencyValues = new Tone.WaveShaper();
|
2014-08-23 17:48:52 +00:00
|
|
|
|
|
|
|
/**
|
2014-10-30 23:44:05 +00:00
|
|
|
* @type {Tone.Subtract}
|
2014-08-23 17:48:52 +00:00
|
|
|
* @private
|
|
|
|
*/
|
2014-10-30 23:44:05 +00:00
|
|
|
this._sub = new Tone.Subtract();
|
2014-06-30 15:34:52 +00:00
|
|
|
|
2014-08-23 17:48:52 +00:00
|
|
|
/**
|
|
|
|
* @type {DelayNode}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._delay = this.context.createDelay();
|
2014-10-20 02:07:18 +00:00
|
|
|
this._delay.delayTime.value = this.bufferTime;
|
2014-08-23 17:48:52 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* this keeps it far from 0, even for very small differences
|
|
|
|
* @type {Tone.Multiply}
|
|
|
|
* @private
|
|
|
|
*/
|
2014-10-30 23:44:05 +00:00
|
|
|
this._mult = new Tone.Multiply(10000);
|
2014-08-23 17:48:52 +00:00
|
|
|
|
2014-08-25 13:57:36 +00:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
* @type {number}
|
|
|
|
*/
|
|
|
|
this._attack = this.secondsToFrequency(options.attack);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
* @type {number}
|
|
|
|
*/
|
|
|
|
this._release = this.secondsToFrequency(options.release);
|
|
|
|
|
2014-08-23 17:48:52 +00:00
|
|
|
//the smoothed signal to get the values
|
2014-12-01 02:32:09 +00:00
|
|
|
this.input.chain(this._abs, this._filter, this.output);
|
2014-08-23 17:48:52 +00:00
|
|
|
//the difference path
|
2014-10-30 23:44:05 +00:00
|
|
|
this._abs.connect(this._sub, 0, 1);
|
2014-12-01 02:32:09 +00:00
|
|
|
this._filter.chain(this._delay, this._sub);
|
2014-08-23 17:48:52 +00:00
|
|
|
//threshold the difference and use the thresh to set the frequency
|
2014-12-01 02:32:09 +00:00
|
|
|
this._sub.chain(this._mult, this._frequencyValues, this._filter.frequency);
|
2014-08-23 17:48:52 +00:00
|
|
|
//set the attack and release values in the table
|
2014-08-25 13:57:36 +00:00
|
|
|
this._setAttackRelease(this._attack, this._release);
|
2014-06-30 15:34:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Tone.extend(Tone.Follower);
|
2014-07-02 22:20:34 +00:00
|
|
|
|
2014-08-24 23:28:42 +00:00
|
|
|
/**
|
|
|
|
* @static
|
|
|
|
* @type {Object}
|
|
|
|
*/
|
2014-08-25 14:23:37 +00:00
|
|
|
Tone.Follower.defaults = {
|
2014-08-24 23:28:42 +00:00
|
|
|
"attack" : 0.05,
|
|
|
|
"release" : 0.5
|
|
|
|
};
|
|
|
|
|
2014-07-23 19:25:46 +00:00
|
|
|
/**
|
2014-08-23 17:48:52 +00:00
|
|
|
* sets the attack and release times in the wave shaper
|
2015-02-02 17:49:13 +00:00
|
|
|
* @param {Tone.Time} attack
|
|
|
|
* @param {Tone.Time} release
|
2014-08-23 17:48:52 +00:00
|
|
|
* @private
|
2014-07-23 19:25:46 +00:00
|
|
|
*/
|
2014-08-23 17:48:52 +00:00
|
|
|
Tone.Follower.prototype._setAttackRelease = function(attack, release){
|
2014-10-20 02:07:18 +00:00
|
|
|
var minTime = this.bufferTime;
|
2015-02-02 17:49:13 +00:00
|
|
|
attack = this.toFrequency(attack);
|
|
|
|
release = this.toFrequency(release);
|
2014-10-13 23:21:34 +00:00
|
|
|
attack = Math.max(attack, minTime);
|
|
|
|
release = Math.max(release, minTime);
|
2014-11-30 18:20:35 +00:00
|
|
|
this._frequencyValues.setMap(function(val){
|
|
|
|
if (val <= 0){
|
|
|
|
return attack;
|
2014-08-23 17:48:52 +00:00
|
|
|
} else {
|
2014-11-30 18:20:35 +00:00
|
|
|
return release;
|
2014-08-23 17:48:52 +00:00
|
|
|
}
|
2014-11-30 18:20:35 +00:00
|
|
|
});
|
2014-07-23 19:25:46 +00:00
|
|
|
};
|
|
|
|
|
2014-08-25 13:57:36 +00:00
|
|
|
/**
|
|
|
|
* set the attack time
|
|
|
|
* @param {Tone.Time} attack
|
2015-02-02 17:49:13 +00:00
|
|
|
* @returns {Tone.Follower} `this`
|
2014-08-25 13:57:36 +00:00
|
|
|
*/
|
|
|
|
Tone.Follower.prototype.setAttack = function(attack){
|
2015-02-02 17:49:13 +00:00
|
|
|
this._attack = attack;
|
2014-08-25 13:57:36 +00:00
|
|
|
this._setAttackRelease(this._attack, this._release);
|
2015-02-02 17:49:13 +00:00
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get the attack time
|
|
|
|
* @returns {Tone.Time} the attack time
|
|
|
|
*/
|
|
|
|
Tone.Follower.prototype.getAttack = function(){
|
|
|
|
return this._attack;
|
2014-08-25 13:57:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set the release time
|
|
|
|
* @param {Tone.Time} release
|
2015-02-02 17:49:13 +00:00
|
|
|
* @returns {Tone.Follower} `this`
|
2014-08-25 13:57:36 +00:00
|
|
|
*/
|
|
|
|
Tone.Follower.prototype.setRelease = function(release){
|
2015-02-02 17:49:13 +00:00
|
|
|
this._release = release;
|
2014-08-25 13:57:36 +00:00
|
|
|
this._setAttackRelease(this._attack, this._release);
|
2015-02-02 17:49:13 +00:00
|
|
|
return this;
|
2014-08-25 13:57:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2015-02-02 17:49:13 +00:00
|
|
|
* get the release time
|
|
|
|
* @returns {Tone.Time} the release time
|
2014-08-25 13:57:36 +00:00
|
|
|
*/
|
2015-02-02 17:49:13 +00:00
|
|
|
Tone.Follower.prototype.getRelease = function(){
|
|
|
|
return this._release;
|
2014-08-25 13:57:36 +00:00
|
|
|
};
|
|
|
|
|
2014-08-29 20:36:52 +00:00
|
|
|
/**
|
|
|
|
* borrows the connect method from Signal so that the output can be used
|
|
|
|
* as a control signal {@link Tone.Signal}
|
|
|
|
*/
|
|
|
|
Tone.Follower.prototype.connect = Tone.Signal.prototype.connect;
|
|
|
|
|
2014-07-02 22:20:34 +00:00
|
|
|
/**
|
|
|
|
* dispose
|
2015-02-02 17:49:13 +00:00
|
|
|
* @returns {Tone.Follower} `this`
|
2014-07-02 22:20:34 +00:00
|
|
|
*/
|
|
|
|
Tone.Follower.prototype.dispose = function(){
|
2014-08-24 20:24:16 +00:00
|
|
|
Tone.prototype.dispose.call(this);
|
2014-08-23 17:48:52 +00:00
|
|
|
this._filter.disconnect();
|
2014-10-30 23:44:05 +00:00
|
|
|
this._filter = null;
|
2014-08-23 17:48:52 +00:00
|
|
|
this._frequencyValues.disconnect();
|
2014-10-30 23:44:05 +00:00
|
|
|
this._frequencyValues = null;
|
2014-08-23 17:48:52 +00:00
|
|
|
this._delay.disconnect();
|
|
|
|
this._delay = null;
|
2014-10-30 23:44:05 +00:00
|
|
|
this._sub.disconnect();
|
|
|
|
this._sub = null;
|
|
|
|
this._abs.dispose();
|
2014-07-02 22:20:34 +00:00
|
|
|
this._abs = null;
|
2014-10-30 23:44:05 +00:00
|
|
|
this._mult.dispose();
|
2014-08-23 17:48:52 +00:00
|
|
|
this._mult = null;
|
2014-11-04 00:22:17 +00:00
|
|
|
this._curve = null;
|
2015-02-02 17:49:13 +00:00
|
|
|
return this;
|
2014-07-02 22:20:34 +00:00
|
|
|
};
|
|
|
|
|
2015-02-02 17:49:13 +00:00
|
|
|
/**
|
|
|
|
* the attack time
|
|
|
|
* @memberOf Tone.Follower#
|
|
|
|
* @type {Tone.Time}
|
|
|
|
* @name attack
|
|
|
|
*/
|
|
|
|
Tone._defineGetterSetter(Tone.Follower, "attack");
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the release time
|
|
|
|
* @memberOf Tone.Follower#
|
|
|
|
* @type {Tone.Time}
|
|
|
|
* @name release
|
|
|
|
*/
|
|
|
|
Tone._defineGetterSetter(Tone.Follower, "release");
|
|
|
|
|
2014-07-02 22:20:34 +00:00
|
|
|
return Tone.Follower;
|
2014-06-30 15:34:52 +00:00
|
|
|
});
|