UNPKG

4.03 kBJavaScriptView Raw
1import { StereoEffect } from "./StereoEffect.js";
2import { optionsFromArguments } from "../core/util/Defaults.js";
3import { readOnly } from "../core/util/Interface.js";
4import { Signal } from "../signal/Signal.js";
5import { LowpassCombFilter } from "../component/filter/LowpassCombFilter.js";
6/**
7 * An array of comb filter delay values from Freeverb implementation
8 */
9const combFilterTunings = [
10 1557 / 44100,
11 1617 / 44100,
12 1491 / 44100,
13 1422 / 44100,
14 1277 / 44100,
15 1356 / 44100,
16 1188 / 44100,
17 1116 / 44100,
18];
19/**
20 * An array of allpass filter frequency values from Freeverb implementation
21 */
22const allpassFilterFrequencies = [225, 556, 441, 341];
23/**
24 * Freeverb is a reverb based on [Freeverb](https://ccrma.stanford.edu/~jos/pasp/Freeverb.html).
25 * Read more on reverb on [Sound On Sound](https://web.archive.org/web/20160404083902/http://www.soundonsound.com:80/sos/feb01/articles/synthsecrets.asp).
26 * Freeverb is now implemented with an AudioWorkletNode which may result on performance degradation on some platforms. Consider using {@link Reverb}.
27 * @example
28 * const freeverb = new Tone.Freeverb().toDestination();
29 * freeverb.dampening = 1000;
30 * // routing synth through the reverb
31 * const synth = new Tone.NoiseSynth().connect(freeverb);
32 * synth.triggerAttackRelease(0.05);
33 * @category Effect
34 */
35export class Freeverb extends StereoEffect {
36 constructor() {
37 const options = optionsFromArguments(Freeverb.getDefaults(), arguments, ["roomSize", "dampening"]);
38 super(options);
39 this.name = "Freeverb";
40 /**
41 * the comb filters
42 */
43 this._combFilters = [];
44 /**
45 * the allpass filters on the left
46 */
47 this._allpassFiltersL = [];
48 /**
49 * the allpass filters on the right
50 */
51 this._allpassFiltersR = [];
52 this.roomSize = new Signal({
53 context: this.context,
54 value: options.roomSize,
55 units: "normalRange",
56 });
57 // make the allpass filters on the right
58 this._allpassFiltersL = allpassFilterFrequencies.map((freq) => {
59 const allpassL = this.context.createBiquadFilter();
60 allpassL.type = "allpass";
61 allpassL.frequency.value = freq;
62 return allpassL;
63 });
64 // make the allpass filters on the left
65 this._allpassFiltersR = allpassFilterFrequencies.map((freq) => {
66 const allpassR = this.context.createBiquadFilter();
67 allpassR.type = "allpass";
68 allpassR.frequency.value = freq;
69 return allpassR;
70 });
71 // make the comb filters
72 this._combFilters = combFilterTunings.map((delayTime, index) => {
73 const lfpf = new LowpassCombFilter({
74 context: this.context,
75 dampening: options.dampening,
76 delayTime,
77 });
78 if (index < combFilterTunings.length / 2) {
79 this.connectEffectLeft(lfpf, ...this._allpassFiltersL);
80 }
81 else {
82 this.connectEffectRight(lfpf, ...this._allpassFiltersR);
83 }
84 this.roomSize.connect(lfpf.resonance);
85 return lfpf;
86 });
87 readOnly(this, ["roomSize"]);
88 }
89 static getDefaults() {
90 return Object.assign(StereoEffect.getDefaults(), {
91 roomSize: 0.7,
92 dampening: 3000,
93 });
94 }
95 /**
96 * The amount of dampening of the reverberant signal.
97 */
98 get dampening() {
99 return this._combFilters[0].dampening;
100 }
101 set dampening(d) {
102 this._combFilters.forEach((c) => (c.dampening = d));
103 }
104 dispose() {
105 super.dispose();
106 this._allpassFiltersL.forEach((al) => al.disconnect());
107 this._allpassFiltersR.forEach((ar) => ar.disconnect());
108 this._combFilters.forEach((cf) => cf.dispose());
109 this.roomSize.dispose();
110 return this;
111 }
112}
113//# sourceMappingURL=Freeverb.js.map
\No newline at end of file