Tone.js/Tone/component/Envelope.js
2014-06-21 15:55:13 -04:00

149 lines
4.5 KiB
JavaScript

define(["Tone/core/Tone", "Tone/signal/Signal"], function(Tone){
/**
* Envelope
* ADR envelope generator attaches to an AudioParam or AudioNode
*
* @constructor
* @extends {Tone}
* @param {Tone.Time=} attack
* @param {Tone.Time=} decay
* @param {number=} sustain a percentage (0-1) of the full amplitude
* @param {Tone.Time=} release
* @param {number=} minOutput the lowest point of the envelope
* @param {number=} maxOutput the highest point of the envelope
*/
Tone.Envelope = function(attack, decay, sustain, release, minOutput, maxOutput){
//extend Unit
Tone.call(this);
/** @type {number} */
this.attack = this.toSeconds(this.defaultArg(attack, 0.01));
/** @type {number} */
this.decay = this.toSeconds(this.defaultArg(decay, 0.1));
/** @type {number} */
this.release = this.toSeconds(this.defaultArg(release, 1));
/** @type {number} */
this.sustain = this.toSeconds(this.defaultArg(sustain, 0.5));
/** @type {number} */
this.min = this.defaultArg(minOutput, 0);
/** @type {number} */
this.max = this.defaultArg(maxOutput, 1);
/** @type {Tone.Signal} */
this.control = new Tone.Signal(this.min);
//connections
this.chain(this.control, this.output);
};
Tone.extend(Tone.Envelope);
/**
* attack->decay->sustain linear ramp
* @param {Tone.Time=} time
*/
Tone.Envelope.prototype.triggerAttack = function(time){
var sustainVal = (this.max - this.min) * this.sustain + this.min;
if (!time){
this.control.linearRampToValueNow(this.max, this.attack);
this.control.linearRampToValueAtTime(sustainVal, this.now() + this.attack + this.decay);
} else {
var startVal = this.min;
time = this.toSeconds(time);
this.control.cancelScheduledValues(time);
this.control.setValueAtTime(startVal, time);
this.control.linearRampToValueAtTime(this.max, time + this.attack);
this.control.linearRampToValueAtTime(sustainVal, time + this.attack + this.decay);
}
};
/**
* attack->decay->sustain exponential attack and linear decay
* @param {Tone.Time=} time
*/
Tone.Envelope.prototype.triggerExponentialAttack = function(time){
var sustainVal = (this.max - this.min) * this.sustain + this.min;
if (!time){
this.control.exponentialRampToValueNow(this.max, this.attack);
this.control.linearRampToValueAtTime(sustainVal, this.now() + this.attack + this.decay);
} else {
var startVal = this.min;
time = this.toSeconds(time);
this.control.cancelScheduledValues(time);
this.control.setValueAtTime(startVal, time);
this.control.exponentialRampToValueAtTime(this.max, time + this.attack);
this.control.linearRampToValueAtTime(sustainVal, time + this.attack + this.decay);
}
};
/**
* triggers the release of the envelope with a linear ramp
* @param {Tone.Time=} time
*/
Tone.Envelope.prototype.triggerRelease = function(time){
if (time){
//if there's a time, start at the sustain value
startVal = (this.max - this.min) * this.sustain + this.min;
time = this.toSeconds(time);
this.control.cancelScheduledValues(time);
this.control.setValueAtTime(startVal, time);
this.control.linearRampToValueAtTime(this.min, time + this.toSeconds(this.release));
} else {
this.control.linearRampToValueNow(this.min, this.toSeconds(this.release));
}
};
/**
* triggers the release of the envelope with an exponential ramp
*
* @param {Tone.Time=} time
*/
Tone.Envelope.prototype.triggerExponentialRelease = function(time){
if (time){
//if there's a time, start at the sustain value
startVal = (this.max - this.min) * this.sustain + this.min;
time = this.toSeconds(time);
this.control.cancelScheduledValues(time);
this.control.setValueAtTime(startVal, time);
this.control.exponentialRampToValueAtTime(this.min, time + this.toSeconds(this.release));
} else {
this.control.exponentialRampToValueNow(this.min, this.toSeconds(this.release));
}
};
/**
* pointer to the parent's connect method
* @private
*/
Tone.Envelope.prototype._connect = Tone.prototype.connect;
/**
* connect the envelope
*
* if the envelope is connected to a param, the params
* value will be set to 0 so that it doesn't interfere with the envelope
*
* @param {number} param
*/
Tone.Envelope.prototype.connect = function(param){
if (param instanceof AudioParam){
//set the initial value
param.value = 0;
}
this._connect(param);
};
/**
* disconnect and dispose
*/
Tone.Envelope.prototype.dispose = function(){
this.control.dispose();
this.control = null;
};
return Tone.Envelope;
});