2017-10-21 23:02:46 +00:00
|
|
|
define(["Tone/core/Tone", "Tone/component/FeedbackCombFilter", "Tone/effect/StereoEffect", "Tone/signal/Scale"], function(Tone){
|
2014-09-21 17:39:18 +00:00
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* an array of the comb filter delay time values
|
|
|
|
* @private
|
|
|
|
* @static
|
|
|
|
* @type {Array}
|
|
|
|
*/
|
|
|
|
var combFilterDelayTimes = [1687 / 25000, 1601 / 25000, 2053 / 25000, 2251 / 25000];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the resonances of each of the comb filters
|
|
|
|
* @private
|
|
|
|
* @static
|
|
|
|
* @type {Array}
|
|
|
|
*/
|
|
|
|
var combFilterResonances = [0.773, 0.802, 0.753, 0.733];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the allpass filter frequencies
|
|
|
|
* @private
|
|
|
|
* @static
|
|
|
|
* @type {Array}
|
|
|
|
*/
|
|
|
|
var allpassFilterFreqs = [347, 113, 37];
|
|
|
|
|
|
|
|
/**
|
2015-07-04 19:25:37 +00:00
|
|
|
* @class Tone.JCReverb is a simple [Schroeder Reverberator](https://ccrma.stanford.edu/~jos/pasp/Schroeder_Reverberators.html)
|
|
|
|
* tuned by John Chowning in 1970.
|
2017-10-21 23:02:46 +00:00
|
|
|
* It is made up of three allpass filters and four Tone.FeedbackCombFilter.
|
|
|
|
*
|
2014-09-21 17:39:18 +00:00
|
|
|
*
|
|
|
|
* @extends {Tone.Effect}
|
|
|
|
* @constructor
|
2015-06-22 05:20:57 +00:00
|
|
|
* @param {NormalRange|Object} [roomSize] Coorelates to the decay time.
|
2015-02-27 21:53:10 +00:00
|
|
|
* @example
|
2015-07-04 16:40:33 +00:00
|
|
|
* var reverb = new Tone.JCReverb(0.4).connect(Tone.Master);
|
2017-10-21 23:02:46 +00:00
|
|
|
* var delay = new Tone.FeedbackDelay(0.5);
|
2015-07-04 16:40:33 +00:00
|
|
|
* //connecting the synth to reverb through delay
|
|
|
|
* var synth = new Tone.DuoSynth().chain(delay, reverb);
|
|
|
|
* synth.triggerAttackRelease("A4","8n");
|
2014-09-21 17:39:18 +00:00
|
|
|
*/
|
|
|
|
Tone.JCReverb = function(){
|
2014-10-03 15:34:47 +00:00
|
|
|
|
2017-04-26 03:18:08 +00:00
|
|
|
var options = Tone.defaults(arguments, ["roomSize"], Tone.JCReverb);
|
2014-10-03 15:34:47 +00:00
|
|
|
Tone.StereoEffect.call(this, options);
|
2014-09-21 17:39:18 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* room size control values between [0,1]
|
2015-06-13 23:50:39 +00:00
|
|
|
* @type {NormalRange}
|
|
|
|
* @signal
|
2014-09-21 17:39:18 +00:00
|
|
|
*/
|
2015-05-24 13:45:15 +00:00
|
|
|
this.roomSize = new Tone.Signal(options.roomSize, Tone.Type.NormalRange);
|
2014-09-21 17:39:18 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* scale the room size
|
|
|
|
* @type {Tone.Scale}
|
|
|
|
* @private
|
|
|
|
*/
|
2014-11-30 02:36:32 +00:00
|
|
|
this._scaleRoomSize = new Tone.Scale(-0.733, 0.197);
|
2014-09-21 17:39:18 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* a series of allpass filters
|
2015-06-14 00:56:41 +00:00
|
|
|
* @type {Array}
|
2014-09-21 17:39:18 +00:00
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._allpassFilters = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* parallel feedback comb filters
|
2015-06-14 00:56:41 +00:00
|
|
|
* @type {Array}
|
2014-09-21 17:39:18 +00:00
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._feedbackCombFilters = [];
|
|
|
|
|
|
|
|
//make the allpass filters
|
|
|
|
for (var af = 0; af < allpassFilterFreqs.length; af++) {
|
|
|
|
var allpass = this.context.createBiquadFilter();
|
|
|
|
allpass.type = "allpass";
|
|
|
|
allpass.frequency.value = allpassFilterFreqs[af];
|
|
|
|
this._allpassFilters.push(allpass);
|
|
|
|
}
|
|
|
|
|
|
|
|
//and the comb filters
|
|
|
|
for (var cf = 0; cf < combFilterDelayTimes.length; cf++) {
|
2014-11-03 16:34:02 +00:00
|
|
|
var fbcf = new Tone.FeedbackCombFilter(combFilterDelayTimes[cf], 0.1);
|
2014-09-21 17:39:18 +00:00
|
|
|
this._scaleRoomSize.connect(fbcf.resonance);
|
2015-02-10 21:44:27 +00:00
|
|
|
fbcf.resonance.value = combFilterResonances[cf];
|
2014-09-21 17:39:18 +00:00
|
|
|
this._allpassFilters[this._allpassFilters.length - 1].connect(fbcf);
|
|
|
|
if (cf < combFilterDelayTimes.length / 2){
|
|
|
|
fbcf.connect(this.effectReturnL);
|
|
|
|
} else {
|
|
|
|
fbcf.connect(this.effectReturnR);
|
|
|
|
}
|
|
|
|
this._feedbackCombFilters.push(fbcf);
|
|
|
|
}
|
|
|
|
|
|
|
|
//chain the allpass filters together
|
|
|
|
this.roomSize.connect(this._scaleRoomSize);
|
2017-05-01 18:06:36 +00:00
|
|
|
Tone.connectSeries.apply(Tone, this._allpassFilters);
|
2014-09-21 17:39:18 +00:00
|
|
|
this.effectSendL.connect(this._allpassFilters[0]);
|
|
|
|
this.effectSendR.connect(this._allpassFilters[0]);
|
2015-04-18 14:54:08 +00:00
|
|
|
this._readOnly(["roomSize"]);
|
2014-09-21 17:39:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Tone.extend(Tone.JCReverb, Tone.StereoEffect);
|
|
|
|
|
2014-10-03 15:34:47 +00:00
|
|
|
/**
|
|
|
|
* the default values
|
|
|
|
* @static
|
|
|
|
* @const
|
|
|
|
* @type {Object}
|
|
|
|
*/
|
|
|
|
Tone.JCReverb.defaults = {
|
|
|
|
"roomSize" : 0.5
|
|
|
|
};
|
|
|
|
|
2014-09-21 17:39:18 +00:00
|
|
|
/**
|
2017-10-21 23:02:46 +00:00
|
|
|
* Clean up.
|
2015-06-14 00:54:29 +00:00
|
|
|
* @returns {Tone.JCReverb} this
|
2014-09-21 17:39:18 +00:00
|
|
|
*/
|
|
|
|
Tone.JCReverb.prototype.dispose = function(){
|
|
|
|
Tone.StereoEffect.prototype.dispose.call(this);
|
|
|
|
for (var apf = 0; apf < this._allpassFilters.length; apf++) {
|
|
|
|
this._allpassFilters[apf].disconnect();
|
|
|
|
this._allpassFilters[apf] = null;
|
|
|
|
}
|
|
|
|
this._allpassFilters = null;
|
|
|
|
for (var fbcf = 0; fbcf < this._feedbackCombFilters.length; fbcf++) {
|
|
|
|
this._feedbackCombFilters[fbcf].dispose();
|
|
|
|
this._feedbackCombFilters[fbcf] = null;
|
|
|
|
}
|
|
|
|
this._feedbackCombFilters = null;
|
2015-04-18 14:54:08 +00:00
|
|
|
this._writable(["roomSize"]);
|
2014-09-21 17:39:18 +00:00
|
|
|
this.roomSize.dispose();
|
|
|
|
this.roomSize = null;
|
2014-10-23 15:41:38 +00:00
|
|
|
this._scaleRoomSize.dispose();
|
2014-09-21 17:39:18 +00:00
|
|
|
this._scaleRoomSize = null;
|
2015-02-02 18:22:16 +00:00
|
|
|
return this;
|
2014-09-21 17:39:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
return Tone.JCReverb;
|
2017-10-21 23:02:46 +00:00
|
|
|
});
|