tone
Version:
A Web Audio framework for making interactive music in the browser.
113 lines • 4.03 kB
JavaScript
import { StereoEffect } from "./StereoEffect.js";
import { optionsFromArguments } from "../core/util/Defaults.js";
import { readOnly } from "../core/util/Interface.js";
import { Signal } from "../signal/Signal.js";
import { LowpassCombFilter } from "../component/filter/LowpassCombFilter.js";
/**
* An array of comb filter delay values from Freeverb implementation
*/
const combFilterTunings = [
1557 / 44100,
1617 / 44100,
1491 / 44100,
1422 / 44100,
1277 / 44100,
1356 / 44100,
1188 / 44100,
1116 / 44100,
];
/**
* An array of allpass filter frequency values from Freeverb implementation
*/
const allpassFilterFrequencies = [225, 556, 441, 341];
/**
* Freeverb is a reverb based on [Freeverb](https://ccrma.stanford.edu/~jos/pasp/Freeverb.html).
* Read more on reverb on [Sound On Sound](https://web.archive.org/web/20160404083902/http://www.soundonsound.com:80/sos/feb01/articles/synthsecrets.asp).
* Freeverb is now implemented with an AudioWorkletNode which may result on performance degradation on some platforms. Consider using {@link Reverb}.
* @example
* const freeverb = new Tone.Freeverb().toDestination();
* freeverb.dampening = 1000;
* // routing synth through the reverb
* const synth = new Tone.NoiseSynth().connect(freeverb);
* synth.triggerAttackRelease(0.05);
* @category Effect
*/
export class Freeverb extends StereoEffect {
constructor() {
const options = optionsFromArguments(Freeverb.getDefaults(), arguments, ["roomSize", "dampening"]);
super(options);
this.name = "Freeverb";
/**
* the comb filters
*/
this._combFilters = [];
/**
* the allpass filters on the left
*/
this._allpassFiltersL = [];
/**
* the allpass filters on the right
*/
this._allpassFiltersR = [];
this.roomSize = new Signal({
context: this.context,
value: options.roomSize,
units: "normalRange",
});
// make the allpass filters on the right
this._allpassFiltersL = allpassFilterFrequencies.map((freq) => {
const allpassL = this.context.createBiquadFilter();
allpassL.type = "allpass";
allpassL.frequency.value = freq;
return allpassL;
});
// make the allpass filters on the left
this._allpassFiltersR = allpassFilterFrequencies.map((freq) => {
const allpassR = this.context.createBiquadFilter();
allpassR.type = "allpass";
allpassR.frequency.value = freq;
return allpassR;
});
// make the comb filters
this._combFilters = combFilterTunings.map((delayTime, index) => {
const lfpf = new LowpassCombFilter({
context: this.context,
dampening: options.dampening,
delayTime,
});
if (index < combFilterTunings.length / 2) {
this.connectEffectLeft(lfpf, ...this._allpassFiltersL);
}
else {
this.connectEffectRight(lfpf, ...this._allpassFiltersR);
}
this.roomSize.connect(lfpf.resonance);
return lfpf;
});
readOnly(this, ["roomSize"]);
}
static getDefaults() {
return Object.assign(StereoEffect.getDefaults(), {
roomSize: 0.7,
dampening: 3000,
});
}
/**
* The amount of dampening of the reverberant signal.
*/
get dampening() {
return this._combFilters[0].dampening;
}
set dampening(d) {
this._combFilters.forEach((c) => (c.dampening = d));
}
dispose() {
super.dispose();
this._allpassFiltersL.forEach((al) => al.disconnect());
this._allpassFiltersR.forEach((ar) => ar.disconnect());
this._combFilters.forEach((cf) => cf.dispose());
this.roomSize.dispose();
return this;
}
}
//# sourceMappingURL=Freeverb.js.map