@logue/reverb 1.3.5 → 1.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/Reverb.d.ts +4 -3
- package/dist/Reverb.es.js +91 -448
- package/dist/Reverb.iife.js +3 -634
- package/dist/Reverb.umd.js +3 -637
- package/package.json +32 -30
package/dist/Reverb.es.js
CHANGED
|
@@ -3,86 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @description JavaScript Reverb effect class
|
|
5
5
|
* @author Logue <logue@hotmail.co.jp>
|
|
6
|
-
* @copyright 2019-
|
|
6
|
+
* @copyright 2019-2024 By Masashi Yoshikawa All rights reserved.
|
|
7
7
|
* @license MIT
|
|
8
|
-
* @version 1.3.
|
|
8
|
+
* @version 1.3.9
|
|
9
9
|
* @see {@link https://github.com/logue/Reverb.js}
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
norm(norm = 1) {
|
|
21
|
-
return (this.int() * INV_MAX - 0.5) * 2 * norm;
|
|
22
|
-
}
|
|
23
|
-
normMinMax(min, max) {
|
|
24
|
-
const x = this.minmax(min, max);
|
|
25
|
-
return this.float() < 0.5 ? x : -x;
|
|
26
|
-
}
|
|
27
|
-
minmax(min, max) {
|
|
28
|
-
return this.float() * (max - min) + min;
|
|
29
|
-
}
|
|
30
|
-
minmaxInt(min, max) {
|
|
31
|
-
min |= 0;
|
|
32
|
-
const range = (max | 0) - min;
|
|
33
|
-
return range ? min + (this.int() % range) : min;
|
|
34
|
-
}
|
|
35
|
-
minmaxUint(min, max) {
|
|
36
|
-
min >>>= 0;
|
|
37
|
-
const range = (max >>> 0) - min;
|
|
38
|
-
return range ? min + (this.int() % range) : min;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const random = Math.random;
|
|
43
|
-
/**
|
|
44
|
-
* A `Math.random()` based {@link IRandom} implementation. Also @see
|
|
45
|
-
* {@link SYSTEM}.
|
|
46
|
-
*/
|
|
47
|
-
class SystemRandom extends ARandom {
|
|
48
|
-
int() {
|
|
49
|
-
return (random() * 4294967296) /* 2**32 */ >>> 0;
|
|
50
|
-
}
|
|
51
|
-
float(norm = 1) {
|
|
52
|
-
return random() * norm;
|
|
53
|
-
}
|
|
54
|
-
norm(norm = 1) {
|
|
55
|
-
return (random() - 0.5) * 2 * norm;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Used as default PRNG throughout most other thi.ng projects, though usually is
|
|
60
|
-
* configurable.
|
|
61
|
-
*/
|
|
62
|
-
const SYSTEM = new SystemRandom();
|
|
63
|
-
|
|
64
|
-
const defaults = {
|
|
65
|
-
noise: "white",
|
|
66
|
-
scale: 1,
|
|
67
|
-
peaks: 2,
|
|
68
|
-
randomAlgorithm: SYSTEM,
|
|
69
|
-
decay: 2,
|
|
70
|
-
delay: 0,
|
|
71
|
-
reverse: false,
|
|
72
|
-
time: 2,
|
|
73
|
-
filterType: "allpass",
|
|
74
|
-
filterFreq: 2200,
|
|
75
|
-
filterQ: 1,
|
|
76
|
-
mix: 0.5,
|
|
77
|
-
once: false
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const Meta = {
|
|
81
|
-
version: "1.3.5",
|
|
82
|
-
date: "2023-11-20T03:01:00.334Z"
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const Noise = {
|
|
12
|
+
import { white as c, violet as m, red as f, pink as b, green as N, blue as g } from "@thi.ng/colored-noise";
|
|
13
|
+
import { take as v } from "@thi.ng/transducers";
|
|
14
|
+
import { SYSTEM as w } from "@thi.ng/random";
|
|
15
|
+
const d = {
|
|
16
|
+
version: "1.3.9",
|
|
17
|
+
date: "2024-04-24T08:29:36.615Z"
|
|
18
|
+
}, o = {
|
|
86
19
|
/** Blue noise */
|
|
87
20
|
blue: "blue",
|
|
88
21
|
/** Brown noise (same as red noise) */
|
|
@@ -97,255 +30,26 @@ const Noise = {
|
|
|
97
30
|
violet: "violet",
|
|
98
31
|
/** White noise */
|
|
99
32
|
white: "white"
|
|
33
|
+
}, y = {
|
|
34
|
+
noise: "white",
|
|
35
|
+
scale: 1,
|
|
36
|
+
peaks: 2,
|
|
37
|
+
randomAlgorithm: w,
|
|
38
|
+
decay: 2,
|
|
39
|
+
delay: 0,
|
|
40
|
+
reverse: !1,
|
|
41
|
+
time: 2,
|
|
42
|
+
filterType: "allpass",
|
|
43
|
+
filterFreq: 2200,
|
|
44
|
+
filterQ: 1,
|
|
45
|
+
mix: 0.5,
|
|
46
|
+
once: !1
|
|
100
47
|
};
|
|
101
|
-
|
|
102
|
-
const DEFAULT_OPTS = {
|
|
103
|
-
bins: 2,
|
|
104
|
-
scale: 1,
|
|
105
|
-
rnd: SYSTEM,
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const preseed = (n, scale, rnd) => {
|
|
109
|
-
const state = new Array(n);
|
|
110
|
-
for (let i = 0; i < n; i++) {
|
|
111
|
-
state[i] = rnd.norm(scale);
|
|
112
|
-
}
|
|
113
|
-
return state;
|
|
114
|
-
};
|
|
115
|
-
const sum = (src) => src.reduce((sum, x) => sum + x, 0);
|
|
116
|
-
function* interleave(a, b) {
|
|
117
|
-
const src = [a[Symbol.iterator](), b[Symbol.iterator]()];
|
|
118
|
-
for (let i = 0; true; i ^= 1) {
|
|
119
|
-
const next = src[i].next();
|
|
120
|
-
if (next.done)
|
|
121
|
-
return;
|
|
122
|
-
yield next.value;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* High-pass filtered noise. Opposite of {@link red}.
|
|
128
|
-
*
|
|
129
|
-
* @param opts -
|
|
130
|
-
*/
|
|
131
|
-
function* blue(opts) {
|
|
132
|
-
const { bins, scale, rnd } = {
|
|
133
|
-
...DEFAULT_OPTS,
|
|
134
|
-
...opts,
|
|
135
|
-
};
|
|
136
|
-
const state = preseed(bins, scale, rnd);
|
|
137
|
-
state.forEach((x, i) => (state[i] = i & 1 ? x : -x));
|
|
138
|
-
const invN = 1 / bins;
|
|
139
|
-
let acc = sum(state);
|
|
140
|
-
for (let i = 0, sign = -1; true; ++i >= bins && (i = 0)) {
|
|
141
|
-
acc -= state[i];
|
|
142
|
-
acc += state[i] = sign * rnd.norm(scale);
|
|
143
|
-
sign ^= 0xfffffffe;
|
|
144
|
-
yield sign * acc * invN;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Band-pass filtered noise (interleaved blue noise). Opposite of
|
|
150
|
-
* {@link violet}.
|
|
151
|
-
*
|
|
152
|
-
* @param opts -
|
|
153
|
-
*/
|
|
154
|
-
const green = (opts) => interleave(blue(opts), blue(opts));
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Returns number of 1 bits in `x`.
|
|
158
|
-
*
|
|
159
|
-
* @param x -
|
|
160
|
-
*/
|
|
161
|
-
const ctz32 = (x) => {
|
|
162
|
-
let c = 32;
|
|
163
|
-
x &= -x;
|
|
164
|
-
x && c--;
|
|
165
|
-
x & 0x0000ffff && (c -= 16);
|
|
166
|
-
x & 0x00ff00ff && (c -= 8);
|
|
167
|
-
x & 0x0f0f0f0f && (c -= 4);
|
|
168
|
-
x & 0x33333333 && (c -= 2);
|
|
169
|
-
x & 0x55555555 && (c -= 1);
|
|
170
|
-
return c;
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Exponential decay (1/f) noise, based on Voss-McCarthy algorithm.
|
|
175
|
-
*
|
|
176
|
-
* @remarks
|
|
177
|
-
* The number of internal states should be in the [4..32] range (default: 8).
|
|
178
|
-
* Due to JS integer limitations, `n` > 32 are meaningless.
|
|
179
|
-
*
|
|
180
|
-
* References:
|
|
181
|
-
*
|
|
182
|
-
* - https://www.dsprelated.com/showarticle/908.php
|
|
183
|
-
* - https://www.firstpr.com.au/dsp/pink-noise/#Voss-McCartney
|
|
184
|
-
*
|
|
185
|
-
* @param opts -
|
|
186
|
-
*/
|
|
187
|
-
function* pink(opts) {
|
|
188
|
-
const { bins, scale, rnd } = {
|
|
189
|
-
...DEFAULT_OPTS,
|
|
190
|
-
bins: 8,
|
|
191
|
-
...opts,
|
|
192
|
-
};
|
|
193
|
-
const state = preseed(bins, scale, rnd);
|
|
194
|
-
const invN = 1 / bins;
|
|
195
|
-
let acc = sum(state);
|
|
196
|
-
for (let i = 0; true; i = (i + 1) >>> 0) {
|
|
197
|
-
const id = ctz32(i) % bins;
|
|
198
|
-
acc -= state[id];
|
|
199
|
-
acc += state[id] = rnd.norm(scale);
|
|
200
|
-
yield acc * invN;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Low-pass filtered noise (same as brown noise). Opposite of {@link blue}.
|
|
206
|
-
*
|
|
207
|
-
* @param opts -
|
|
208
|
-
*/
|
|
209
|
-
function* red(opts) {
|
|
210
|
-
const { bins, scale, rnd } = {
|
|
211
|
-
...DEFAULT_OPTS,
|
|
212
|
-
...opts,
|
|
213
|
-
};
|
|
214
|
-
const state = preseed(bins, scale, rnd);
|
|
215
|
-
const invN = 1 / bins;
|
|
216
|
-
let acc = sum(state);
|
|
217
|
-
for (let i = 0; true; ++i >= bins && (i = 0)) {
|
|
218
|
-
acc -= state[i];
|
|
219
|
-
acc += state[i] = rnd.norm(scale);
|
|
220
|
-
yield acc * invN;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Band-stop filtered noise (interleaved red noise). Opposite of {@link green}.
|
|
226
|
-
*
|
|
227
|
-
* @param opts -
|
|
228
|
-
*/
|
|
229
|
-
const violet = (opts) => interleave(red(opts), red(opts));
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Unfiltered noise w/ uniform distribution. Merely yields samples from
|
|
233
|
-
* given PRNG.
|
|
234
|
-
*
|
|
235
|
-
* @param opts -
|
|
236
|
-
*/
|
|
237
|
-
function* white(opts) {
|
|
238
|
-
const { scale, rnd } = { ...DEFAULT_OPTS, ...opts };
|
|
239
|
-
while (true) {
|
|
240
|
-
yield rnd.norm(scale);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const implementsFunction = (x, fn) => x != null && typeof x[fn] === "function";
|
|
245
|
-
|
|
246
|
-
const ensureTransducer = (x) => implementsFunction(x, "xform") ? x.xform() : x;
|
|
247
|
-
|
|
248
|
-
const isIterable = (x) => x != null && typeof x[Symbol.iterator] === "function";
|
|
249
|
-
|
|
250
|
-
class Reduced {
|
|
251
|
-
value;
|
|
252
|
-
constructor(val) {
|
|
253
|
-
this.value = val;
|
|
254
|
-
}
|
|
255
|
-
deref() {
|
|
256
|
-
return this.value;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
const reduced = (x) => new Reduced(x);
|
|
260
|
-
const isReduced = (x) => x instanceof Reduced;
|
|
261
|
-
const ensureReduced = (x) => x instanceof Reduced ? x : new Reduced(x);
|
|
262
|
-
const unreduced = (x) => (x instanceof Reduced ? x.deref() : x);
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Convenience helper for building a full {@link Reducer} using the identity
|
|
266
|
-
* function (i.e. `(x) => x`) as completion step (true for 90% of all
|
|
267
|
-
* bundled transducers).
|
|
268
|
-
*
|
|
269
|
-
* @param init - init step of reducer
|
|
270
|
-
* @param rfn - reduction step of reducer
|
|
271
|
-
*/
|
|
272
|
-
const reducer = (init, rfn) => [init, (acc) => acc, rfn];
|
|
273
|
-
|
|
274
|
-
function push(xs) {
|
|
275
|
-
return xs
|
|
276
|
-
? [...xs]
|
|
277
|
-
: reducer(() => [], (acc, x) => (acc.push(x), acc));
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Takes a transducer and input iterable. Returns iterator of
|
|
282
|
-
* transformed results.
|
|
283
|
-
*
|
|
284
|
-
* @param xform -
|
|
285
|
-
* @param xs -
|
|
286
|
-
*/
|
|
287
|
-
function* iterator(xform, xs) {
|
|
288
|
-
const rfn = ensureTransducer(xform)(push());
|
|
289
|
-
const complete = rfn[1];
|
|
290
|
-
const reduce = rfn[2];
|
|
291
|
-
for (let x of xs) {
|
|
292
|
-
const y = reduce([], x);
|
|
293
|
-
if (isReduced(y)) {
|
|
294
|
-
yield* unreduced(complete(y.deref()));
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
if (y.length) {
|
|
298
|
-
yield* y;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
yield* unreduced(complete([]));
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Reducer composition helper, internally used by various transducers
|
|
306
|
-
* during initialization. Takes existing reducer `rfn` (a 3-tuple) and a
|
|
307
|
-
* reducing function `fn`. Returns a new reducer tuple.
|
|
308
|
-
*
|
|
309
|
-
* @remarks
|
|
310
|
-
* `rfn[2]` reduces values of type `B` into an accumulator of type `A`.
|
|
311
|
-
* `fn` accepts values of type `C` and produces interim results of type
|
|
312
|
-
* `B`, which are then (possibly) passed to the "inner" `rfn[2]`
|
|
313
|
-
* function. Therefore the resulting reducer takes inputs of `C` and an
|
|
314
|
-
* accumulator of type `A`.
|
|
315
|
-
*
|
|
316
|
-
* It is assumed that `fn` internally calls `rfn[2]` to pass its own
|
|
317
|
-
* results for further processing by the nested reducer `rfn`.
|
|
318
|
-
*
|
|
319
|
-
* @example
|
|
320
|
-
* ```ts
|
|
321
|
-
* compR(rfn, fn)
|
|
322
|
-
* // [rfn[0], rfn[1], fn]
|
|
323
|
-
* ```
|
|
324
|
-
*
|
|
325
|
-
* @param rfn -
|
|
326
|
-
* @param fn -
|
|
327
|
-
*/
|
|
328
|
-
const compR = (rfn, fn) => [rfn[0], rfn[1], fn];
|
|
329
|
-
|
|
330
|
-
function take(n, src) {
|
|
331
|
-
return isIterable(src)
|
|
332
|
-
? iterator(take(n), src)
|
|
333
|
-
: (rfn) => {
|
|
334
|
-
const r = rfn[2];
|
|
335
|
-
let m = n;
|
|
336
|
-
return compR(rfn, (acc, x) => --m > 0
|
|
337
|
-
? r(acc, x)
|
|
338
|
-
: m === 0
|
|
339
|
-
? ensureReduced(r(acc, x))
|
|
340
|
-
: reduced(acc));
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
class Reverb {
|
|
48
|
+
class s {
|
|
345
49
|
/** Version strings */
|
|
346
|
-
static version =
|
|
50
|
+
static version = d.version;
|
|
347
51
|
/** Build date */
|
|
348
|
-
static build =
|
|
52
|
+
static build = d.date;
|
|
349
53
|
/** AudioContext */
|
|
350
54
|
ctx;
|
|
351
55
|
/** Wet Level (Reverberated node) */
|
|
@@ -363,211 +67,167 @@ class Reverb {
|
|
|
363
67
|
/** Connected flag */
|
|
364
68
|
isConnected;
|
|
365
69
|
/** Noise Generator */
|
|
366
|
-
noise =
|
|
70
|
+
noise = c;
|
|
367
71
|
/**
|
|
368
72
|
* Constructor
|
|
369
73
|
*
|
|
370
74
|
* @param ctx - Root AudioContext
|
|
371
75
|
* @param options - Configure
|
|
372
76
|
*/
|
|
373
|
-
constructor(
|
|
374
|
-
this.ctx = ctx;
|
|
375
|
-
this.options = Object.assign(defaults, options);
|
|
376
|
-
this.wetGainNode = this.ctx.createGain();
|
|
377
|
-
this.dryGainNode = this.ctx.createGain();
|
|
378
|
-
this.filterNode = this.ctx.createBiquadFilter();
|
|
379
|
-
this.convolverNode = this.ctx.createConvolver();
|
|
380
|
-
this.outputNode = this.ctx.createGain();
|
|
381
|
-
this.isConnected = false;
|
|
382
|
-
this.filterType(this.options.filterType);
|
|
383
|
-
this.setNoise(this.options.noise);
|
|
384
|
-
this.buildImpulse();
|
|
385
|
-
this.mix(this.options.mix);
|
|
77
|
+
constructor(e, t) {
|
|
78
|
+
this.ctx = e, this.options = Object.assign(y, t), this.wetGainNode = this.ctx.createGain(), this.dryGainNode = this.ctx.createGain(), this.filterNode = this.ctx.createBiquadFilter(), this.convolverNode = this.ctx.createConvolver(), this.outputNode = this.ctx.createGain(), this.isConnected = !1, this.filterType(this.options.filterType), this.setNoise(this.options.noise), this.buildImpulse(), this.mix(this.options.mix);
|
|
386
79
|
}
|
|
387
80
|
/**
|
|
388
81
|
* Connect the node for the reverb effect to the original sound node.
|
|
389
82
|
*
|
|
390
83
|
* @param sourceNode - Input source node
|
|
391
84
|
*/
|
|
392
|
-
connect(
|
|
393
|
-
|
|
394
|
-
this.isConnected = false;
|
|
395
|
-
return this.outputNode;
|
|
396
|
-
}
|
|
397
|
-
this.convolverNode.connect(this.filterNode);
|
|
398
|
-
this.filterNode.connect(this.wetGainNode);
|
|
399
|
-
sourceNode.connect(this.convolverNode);
|
|
400
|
-
sourceNode.connect(this.dryGainNode).connect(this.outputNode);
|
|
401
|
-
sourceNode.connect(this.wetGainNode).connect(this.outputNode);
|
|
402
|
-
this.isConnected = true;
|
|
403
|
-
return this.outputNode;
|
|
85
|
+
connect(e) {
|
|
86
|
+
return this.isConnected && this.options.once ? (this.isConnected = !1, this.outputNode) : (this.convolverNode.connect(this.filterNode), this.filterNode.connect(this.wetGainNode), e.connect(this.convolverNode), e.connect(this.dryGainNode).connect(this.outputNode), e.connect(this.wetGainNode).connect(this.outputNode), this.isConnected = !0, this.outputNode);
|
|
404
87
|
}
|
|
405
88
|
/**
|
|
406
89
|
* Disconnect the reverb node
|
|
407
90
|
*
|
|
408
91
|
* @param sourceNode - Input source node
|
|
409
92
|
*/
|
|
410
|
-
disconnect(
|
|
411
|
-
|
|
412
|
-
this.convolverNode.disconnect(this.filterNode);
|
|
413
|
-
this.filterNode.disconnect(this.wetGainNode);
|
|
414
|
-
}
|
|
415
|
-
this.isConnected = false;
|
|
416
|
-
return sourceNode;
|
|
93
|
+
disconnect(e) {
|
|
94
|
+
return this.isConnected && (this.convolverNode.disconnect(this.filterNode), this.filterNode.disconnect(this.wetGainNode)), this.isConnected = !1, e;
|
|
417
95
|
}
|
|
418
96
|
/**
|
|
419
97
|
* Dry/Wet ratio
|
|
420
98
|
*
|
|
421
99
|
* @param mix - Ratio (0~1)
|
|
422
100
|
*/
|
|
423
|
-
mix(
|
|
424
|
-
if (!
|
|
101
|
+
mix(e) {
|
|
102
|
+
if (!s.inRange(e, 0, 1))
|
|
425
103
|
throw new RangeError("[Reverb.js] Dry/Wet ratio must be between 0 to 1.");
|
|
426
|
-
|
|
427
|
-
this.options.mix = mix;
|
|
428
|
-
this.dryGainNode.gain.value = 1 - this.options.mix;
|
|
429
|
-
this.wetGainNode.gain.value = this.options.mix;
|
|
104
|
+
this.options.mix = e, this.dryGainNode.gain.value = 1 - this.options.mix, this.wetGainNode.gain.value = this.options.mix;
|
|
430
105
|
}
|
|
431
106
|
/**
|
|
432
107
|
* Set Impulse Response time length (second)
|
|
433
108
|
*
|
|
434
109
|
* @param value - IR length
|
|
435
110
|
*/
|
|
436
|
-
time(
|
|
437
|
-
if (!
|
|
111
|
+
time(e) {
|
|
112
|
+
if (!s.inRange(e, 1, 50))
|
|
438
113
|
throw new RangeError(
|
|
439
114
|
"[Reverb.js] Time length of inpulse response must be less than 50sec."
|
|
440
115
|
);
|
|
441
|
-
|
|
442
|
-
this.options.time = value;
|
|
443
|
-
this.buildImpulse();
|
|
116
|
+
this.options.time = e, this.buildImpulse();
|
|
444
117
|
}
|
|
445
118
|
/**
|
|
446
119
|
* Impulse response decay rate.
|
|
447
120
|
*
|
|
448
121
|
* @param value - Decay value
|
|
449
122
|
*/
|
|
450
|
-
decay(
|
|
451
|
-
if (!
|
|
123
|
+
decay(e) {
|
|
124
|
+
if (!s.inRange(e, 0, 100))
|
|
452
125
|
throw new RangeError(
|
|
453
126
|
"[Reverb.js] Inpulse Response decay level must be less than 100."
|
|
454
127
|
);
|
|
455
|
-
|
|
456
|
-
this.options.decay = value;
|
|
457
|
-
this.buildImpulse();
|
|
128
|
+
this.options.decay = e, this.buildImpulse();
|
|
458
129
|
}
|
|
459
130
|
/**
|
|
460
131
|
* Delay before reverberation starts
|
|
461
132
|
*
|
|
462
133
|
* @param value - Time[ms]
|
|
463
134
|
*/
|
|
464
|
-
delay(
|
|
465
|
-
if (!
|
|
135
|
+
delay(e) {
|
|
136
|
+
if (!s.inRange(e, 0, 100))
|
|
466
137
|
throw new RangeError(
|
|
467
138
|
"[Reverb.js] Inpulse Response delay time must be less than 100."
|
|
468
139
|
);
|
|
469
|
-
|
|
470
|
-
this.options.delay = value;
|
|
471
|
-
this.buildImpulse();
|
|
140
|
+
this.options.delay = e, this.buildImpulse();
|
|
472
141
|
}
|
|
473
142
|
/**
|
|
474
143
|
* Reverse the impulse response.
|
|
475
144
|
*
|
|
476
145
|
* @param reverse - Reverse IR
|
|
477
146
|
*/
|
|
478
|
-
reverse(
|
|
479
|
-
this.options.reverse =
|
|
480
|
-
this.buildImpulse();
|
|
147
|
+
reverse(e) {
|
|
148
|
+
this.options.reverse = e, this.buildImpulse();
|
|
481
149
|
}
|
|
482
150
|
/**
|
|
483
151
|
* Filter for impulse response
|
|
484
152
|
*
|
|
485
153
|
* @param type - Filiter Type
|
|
486
154
|
*/
|
|
487
|
-
filterType(
|
|
488
|
-
this.filterNode.type = this.options.filterType =
|
|
155
|
+
filterType(e = "allpass") {
|
|
156
|
+
this.filterNode.type = this.options.filterType = e;
|
|
489
157
|
}
|
|
490
158
|
/**
|
|
491
159
|
* Filter frequency applied to impulse response
|
|
492
160
|
*
|
|
493
161
|
* @param freq - Frequency
|
|
494
162
|
*/
|
|
495
|
-
filterFreq(
|
|
496
|
-
if (!
|
|
163
|
+
filterFreq(e) {
|
|
164
|
+
if (!s.inRange(e, 20, 2e4))
|
|
497
165
|
throw new RangeError(
|
|
498
166
|
"[Reverb.js] Filter frequrncy must be between 20 and 20000."
|
|
499
167
|
);
|
|
500
|
-
|
|
501
|
-
this.options.filterFreq = freq;
|
|
502
|
-
this.filterNode.frequency.value = this.options.filterFreq;
|
|
168
|
+
this.options.filterFreq = e, this.filterNode.frequency.value = this.options.filterFreq;
|
|
503
169
|
}
|
|
504
170
|
/**
|
|
505
171
|
* Filter quality.
|
|
506
172
|
*
|
|
507
173
|
* @param q - Quality
|
|
508
174
|
*/
|
|
509
|
-
filterQ(
|
|
510
|
-
if (!
|
|
175
|
+
filterQ(e) {
|
|
176
|
+
if (!s.inRange(e, 0, 10))
|
|
511
177
|
throw new RangeError(
|
|
512
|
-
"[Reverb.js] Filter
|
|
178
|
+
"[Reverb.js] Filter Q value must be between 0 and 10."
|
|
513
179
|
);
|
|
514
|
-
|
|
515
|
-
this.options.filterQ = q;
|
|
516
|
-
this.filterNode.Q.value = this.options.filterQ;
|
|
180
|
+
this.options.filterQ = e, this.filterNode.Q.value = this.options.filterQ;
|
|
517
181
|
}
|
|
518
182
|
/**
|
|
519
183
|
* set IR source noise peaks
|
|
520
184
|
*
|
|
521
185
|
* @param p - Peaks
|
|
522
186
|
*/
|
|
523
|
-
peaks(
|
|
524
|
-
this.options.peaks =
|
|
525
|
-
this.buildImpulse();
|
|
187
|
+
peaks(e) {
|
|
188
|
+
this.options.peaks = e, this.buildImpulse();
|
|
526
189
|
}
|
|
527
190
|
/**
|
|
528
191
|
* set IR source noise scale.
|
|
529
192
|
*
|
|
530
193
|
* @param s - Scale
|
|
531
194
|
*/
|
|
532
|
-
scale(
|
|
533
|
-
this.options.scale =
|
|
534
|
-
this.buildImpulse();
|
|
195
|
+
scale(e) {
|
|
196
|
+
this.options.scale = e, this.buildImpulse();
|
|
535
197
|
}
|
|
536
198
|
/**
|
|
537
199
|
* set IR source noise generator.
|
|
538
200
|
*
|
|
539
201
|
* @param a - Algorithm
|
|
540
202
|
*/
|
|
541
|
-
randomAlgorithm(
|
|
542
|
-
this.options.randomAlgorithm =
|
|
543
|
-
this.buildImpulse();
|
|
203
|
+
randomAlgorithm(e) {
|
|
204
|
+
this.options.randomAlgorithm = e, this.buildImpulse();
|
|
544
205
|
}
|
|
545
206
|
/**
|
|
546
207
|
* Inpulse Response Noise algorithm.
|
|
547
208
|
*
|
|
548
209
|
* @param type - IR noise algorithm type.
|
|
549
210
|
*/
|
|
550
|
-
setNoise(
|
|
551
|
-
this.options.noise =
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
this.noise = blue;
|
|
211
|
+
setNoise(e) {
|
|
212
|
+
switch (this.options.noise = e, e) {
|
|
213
|
+
case o.blue:
|
|
214
|
+
this.noise = g;
|
|
555
215
|
break;
|
|
556
|
-
case
|
|
557
|
-
this.noise =
|
|
216
|
+
case o.green:
|
|
217
|
+
this.noise = N;
|
|
558
218
|
break;
|
|
559
|
-
case
|
|
560
|
-
this.noise =
|
|
219
|
+
case o.pink:
|
|
220
|
+
this.noise = b;
|
|
561
221
|
break;
|
|
562
|
-
case
|
|
563
|
-
case
|
|
564
|
-
this.noise =
|
|
222
|
+
case o.red:
|
|
223
|
+
case o.brown:
|
|
224
|
+
this.noise = f;
|
|
565
225
|
break;
|
|
566
|
-
case
|
|
567
|
-
this.noise =
|
|
226
|
+
case o.violet:
|
|
227
|
+
this.noise = m;
|
|
568
228
|
break;
|
|
569
229
|
default:
|
|
570
|
-
this.noise =
|
|
230
|
+
this.noise = c;
|
|
571
231
|
}
|
|
572
232
|
this.buildImpulse();
|
|
573
233
|
}
|
|
@@ -576,9 +236,8 @@ class Reverb {
|
|
|
576
236
|
*
|
|
577
237
|
* @param algorithm - Algorythm
|
|
578
238
|
*/
|
|
579
|
-
setRandomAlgorythm(
|
|
580
|
-
this.options.randomAlgorithm =
|
|
581
|
-
this.buildImpulse();
|
|
239
|
+
setRandomAlgorythm(e) {
|
|
240
|
+
this.options.randomAlgorithm = e, this.buildImpulse();
|
|
582
241
|
}
|
|
583
242
|
/**
|
|
584
243
|
* Return true if in range, otherwise false
|
|
@@ -587,44 +246,27 @@ class Reverb {
|
|
|
587
246
|
* @param min - Minimum value
|
|
588
247
|
* @param max - Maximum value
|
|
589
248
|
*/
|
|
590
|
-
static inRange(
|
|
591
|
-
return (
|
|
249
|
+
static inRange(e, t, n) {
|
|
250
|
+
return (e - t) * (e - n) <= 0;
|
|
592
251
|
}
|
|
593
252
|
/** Utility function for building an impulse response from the module parameters. */
|
|
594
253
|
buildImpulse() {
|
|
595
|
-
const
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
const impulseL = new Float32Array(duration);
|
|
600
|
-
const impulseR = new Float32Array(duration);
|
|
601
|
-
const noiseL = this.getNoise(duration);
|
|
602
|
-
const noiseR = this.getNoise(duration);
|
|
603
|
-
for (let i = 0; i < duration; i++) {
|
|
604
|
-
let n = 0;
|
|
605
|
-
if (i < delayDuration) {
|
|
606
|
-
impulseL[i] = 0;
|
|
607
|
-
impulseR[i] = 0;
|
|
608
|
-
n = this.options.reverse ?? false ? duration - (i - delayDuration) : i - delayDuration;
|
|
609
|
-
} else {
|
|
610
|
-
n = this.options.reverse ?? false ? duration - i : i;
|
|
611
|
-
}
|
|
612
|
-
impulseL[i] = (noiseL[i] ?? 0) * (1 - n / duration) ** this.options.decay;
|
|
613
|
-
impulseR[i] = (noiseR[i] ?? 0) * (1 - n / duration) ** this.options.decay;
|
|
254
|
+
const e = this.ctx.sampleRate, t = Math.max(e * this.options.time, 1), n = e * this.options.delay, a = this.ctx.createBuffer(2, t, e), h = new Float32Array(t), l = new Float32Array(t), p = this.getNoise(t), u = this.getNoise(t);
|
|
255
|
+
for (let i = 0; i < t; i++) {
|
|
256
|
+
let r = 0;
|
|
257
|
+
i < n ? (h[i] = 0, l[i] = 0, r = this.options.reverse ?? !1 ? t - (i - n) : i - n) : r = this.options.reverse ?? !1 ? t - i : i, h[i] = (p[i] ?? 0) * (1 - r / t) ** this.options.decay, l[i] = (u[i] ?? 0) * (1 - r / t) ** this.options.decay;
|
|
614
258
|
}
|
|
615
|
-
|
|
616
|
-
impulse.getChannelData(1).set(impulseR);
|
|
617
|
-
this.convolverNode.buffer = impulse;
|
|
259
|
+
a.getChannelData(0).set(h), a.getChannelData(1).set(l), this.convolverNode.buffer = a;
|
|
618
260
|
}
|
|
619
261
|
/**
|
|
620
262
|
* Noise source
|
|
621
263
|
*
|
|
622
264
|
* @param duration - length of IR.
|
|
623
265
|
*/
|
|
624
|
-
getNoise(
|
|
266
|
+
getNoise(e) {
|
|
625
267
|
return [
|
|
626
|
-
...
|
|
627
|
-
|
|
268
|
+
...v(
|
|
269
|
+
e,
|
|
628
270
|
this.noise({
|
|
629
271
|
bins: this.options.peaks,
|
|
630
272
|
scale: this.options.scale,
|
|
@@ -634,5 +276,6 @@ class Reverb {
|
|
|
634
276
|
];
|
|
635
277
|
}
|
|
636
278
|
}
|
|
637
|
-
|
|
638
|
-
|
|
279
|
+
export {
|
|
280
|
+
s as default
|
|
281
|
+
};
|