UNPKG

4 kBJavaScriptView Raw
1import { __awaiter } from "tslib";
2import { Merge } from "../component/channel/Merge.js";
3import { Gain } from "../core/context/Gain.js";
4import { optionsFromArguments } from "../core/util/Defaults.js";
5import { Noise } from "../source/Noise.js";
6import { Effect } from "./Effect.js";
7import { OfflineContext } from "../core/context/OfflineContext.js";
8import { noOp } from "../core/util/Interface.js";
9import { assertRange } from "../core/util/Debug.js";
10/**
11 * Simple convolution created with decaying noise.
12 * Generates an Impulse Response Buffer
13 * with Tone.Offline then feeds the IR into ConvolverNode.
14 * The impulse response generation is async, so you have
15 * to wait until {@link ready} resolves before it will make a sound.
16 *
17 * Inspiration from [ReverbGen](https://github.com/adelespinasse/reverbGen).
18 * Copyright (c) 2014 Alan deLespinasse Apache 2.0 License.
19 *
20 * @category Effect
21 */
22export class Reverb extends Effect {
23 constructor() {
24 const options = optionsFromArguments(Reverb.getDefaults(), arguments, [
25 "decay",
26 ]);
27 super(options);
28 this.name = "Reverb";
29 /**
30 * Convolver node
31 */
32 this._convolver = this.context.createConvolver();
33 /**
34 * Resolves when the reverb buffer is generated. Whenever either {@link decay}
35 * or {@link preDelay} are set, you have to wait until {@link ready} resolves
36 * before the IR is generated with the latest values.
37 */
38 this.ready = Promise.resolve();
39 this._decay = options.decay;
40 this._preDelay = options.preDelay;
41 this.generate();
42 this.connectEffect(this._convolver);
43 }
44 static getDefaults() {
45 return Object.assign(Effect.getDefaults(), {
46 decay: 1.5,
47 preDelay: 0.01,
48 });
49 }
50 /**
51 * The duration of the reverb.
52 */
53 get decay() {
54 return this._decay;
55 }
56 set decay(time) {
57 time = this.toSeconds(time);
58 assertRange(time, 0.001);
59 this._decay = time;
60 this.generate();
61 }
62 /**
63 * The amount of time before the reverb is fully ramped in.
64 */
65 get preDelay() {
66 return this._preDelay;
67 }
68 set preDelay(time) {
69 time = this.toSeconds(time);
70 assertRange(time, 0);
71 this._preDelay = time;
72 this.generate();
73 }
74 /**
75 * Generate the Impulse Response. Returns a promise while the IR is being generated.
76 * @return Promise which returns this object.
77 */
78 generate() {
79 return __awaiter(this, void 0, void 0, function* () {
80 const previousReady = this.ready;
81 // create a noise burst which decays over the duration in each channel
82 const context = new OfflineContext(2, this._decay + this._preDelay, this.context.sampleRate);
83 const noiseL = new Noise({ context });
84 const noiseR = new Noise({ context });
85 const merge = new Merge({ context });
86 noiseL.connect(merge, 0, 0);
87 noiseR.connect(merge, 0, 1);
88 const gainNode = new Gain({ context }).toDestination();
89 merge.connect(gainNode);
90 noiseL.start(0);
91 noiseR.start(0);
92 // predelay
93 gainNode.gain.setValueAtTime(0, 0);
94 gainNode.gain.setValueAtTime(1, this._preDelay);
95 // decay
96 gainNode.gain.exponentialApproachValueAtTime(0, this._preDelay, this.decay);
97 // render the buffer
98 const renderPromise = context.render();
99 this.ready = renderPromise.then(noOp);
100 // wait for the previous `ready` to resolve
101 yield previousReady;
102 // set the buffer
103 this._convolver.buffer = (yield renderPromise).get();
104 return this;
105 });
106 }
107 dispose() {
108 super.dispose();
109 this._convolver.disconnect();
110 return this;
111 }
112}
113//# sourceMappingURL=Reverb.js.map
\No newline at end of file