@logue/reverb 1.2.0 → 1.2.1
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/dist/NoiseType.d.ts +1 -1
- package/dist/NoiseType.d.ts.map +1 -1
- package/dist/Reverb.d.ts.map +1 -1
- package/dist/Reverb.es.js +19 -279
- package/dist/Reverb.iife.js +26 -294
- package/dist/Reverb.umd.js +28 -294
- package/package.json +20 -17
package/dist/NoiseType.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Impulse response noise generation algorithm */
|
|
2
2
|
declare const Noise: Record<string, string>;
|
|
3
3
|
/** Noise Type */
|
|
4
|
-
export
|
|
4
|
+
export type NoiseType = typeof Noise[keyof typeof Noise];
|
|
5
5
|
/** Noise */
|
|
6
6
|
export default Noise;
|
|
7
7
|
//# sourceMappingURL=NoiseType.d.ts.map
|
package/dist/NoiseType.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NoiseType.d.ts","sourceRoot":"","sources":["../src/NoiseType.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,QAAA,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAexB,CAAC;AAEX,iBAAiB;AACjB,
|
|
1
|
+
{"version":3,"file":"NoiseType.d.ts","sourceRoot":"","sources":["../src/NoiseType.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,QAAA,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAexB,CAAC;AAEX,iBAAiB;AACjB,MAAM,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;AAEzD,YAAY;AACZ,eAAe,KAAK,CAAC"}
|
package/dist/Reverb.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Reverb.d.ts","sourceRoot":"","sources":["../src/Reverb.ts"],"names":[],"mappings":"AAEA,OAAc,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,eAAe,MAAM,8BAA8B,CAAC;AAIhE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,MAAM;IACzB,sBAAsB;IACtB,MAAM,CAAC,OAAO,EAAE,MAAM,CAAgB;IACtC,iBAAiB;IACjB,MAAM,CAAC,KAAK,EAAE,MAAM,CAAa;IACjC,mBAAmB;IACnB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,oCAAoC;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAW;IACvC,sCAAsC;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAW;IACvC,8BAA8B;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;IAC9C,qDAAqD;IACrD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,uBAAuB;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IACtC,aAAa;IACb,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,qBAAqB;IACrB,OAAO,CAAC,WAAW,CAAU;IAC7B,sBAAsB;IACtB,OAAO,CAAC,KAAK,CAAmB;IAEhC;;;;;OAKG;gBACS,GAAG,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,eAAe;IAqBxD;;;;OAIG;IACI,OAAO,CAAC,UAAU,EAAE,SAAS,GAAG,SAAS;IAsBhD;;;;OAIG;IACI,UAAU,CAAC,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS;IAehE;;;;OAIG;IACI,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAU7B;;;;OAIG;IACI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAahC;;;;OAIG;IACI,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAWjC;;;;OAIG;IACI,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAajC;;;;OAIG;IACI,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAQtC;;;;OAIG;IACI,UAAU,CAAC,IAAI,GAAE,gBAA4B,GAAG,IAAI;IAK3D;;;;OAIG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAWrC;;;;OAIG;IACI,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAW/B;;;;OAIG;IACI,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAM7B;;;;OAIG;IACI,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAM7B;;;;OAIG;IACI,eAAe,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;IAMtC;;;;OAIG;IACI,QAAQ,CAAC,IAAI,EAAE,SAAS;IA0B/B;;;;OAIG;IACI,kBAAkB,CAAC,SAAS,EAAE,KAAK;IAK1C;;;;;;OAMG;IACH,OAAO,CAAC,OAAO;IAIf,oFAAoF;IACpF,OAAO,CAAC,YAAY;IA+CpB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;
|
|
1
|
+
{"version":3,"file":"Reverb.d.ts","sourceRoot":"","sources":["../src/Reverb.ts"],"names":[],"mappings":"AAEA,OAAc,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,eAAe,MAAM,8BAA8B,CAAC;AAIhE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,MAAM;IACzB,sBAAsB;IACtB,MAAM,CAAC,OAAO,EAAE,MAAM,CAAgB;IACtC,iBAAiB;IACjB,MAAM,CAAC,KAAK,EAAE,MAAM,CAAa;IACjC,mBAAmB;IACnB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,oCAAoC;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAW;IACvC,sCAAsC;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAW;IACvC,8BAA8B;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;IAC9C,qDAAqD;IACrD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,uBAAuB;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IACtC,aAAa;IACb,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,qBAAqB;IACrB,OAAO,CAAC,WAAW,CAAU;IAC7B,sBAAsB;IACtB,OAAO,CAAC,KAAK,CAAmB;IAEhC;;;;;OAKG;gBACS,GAAG,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,eAAe;IAqBxD;;;;OAIG;IACI,OAAO,CAAC,UAAU,EAAE,SAAS,GAAG,SAAS;IAsBhD;;;;OAIG;IACI,UAAU,CAAC,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS;IAehE;;;;OAIG;IACI,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAU7B;;;;OAIG;IACI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAahC;;;;OAIG;IACI,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAWjC;;;;OAIG;IACI,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAajC;;;;OAIG;IACI,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAQtC;;;;OAIG;IACI,UAAU,CAAC,IAAI,GAAE,gBAA4B,GAAG,IAAI;IAK3D;;;;OAIG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAWrC;;;;OAIG;IACI,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAW/B;;;;OAIG;IACI,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAM7B;;;;OAIG;IACI,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAM7B;;;;OAIG;IACI,eAAe,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;IAMtC;;;;OAIG;IACI,QAAQ,CAAC,IAAI,EAAE,SAAS;IA0B/B;;;;OAIG;IACI,kBAAkB,CAAC,SAAS,EAAE,KAAK;IAK1C;;;;;;OAMG;IACH,OAAO,CAAC,OAAO;IAIf,oFAAoF;IACpF,OAAO,CAAC,YAAY;IA+CpB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;CAYjB"}
|
package/dist/Reverb.es.js
CHANGED
|
@@ -5,10 +5,14 @@
|
|
|
5
5
|
* @author Logue <logue@hotmail.co.jp>
|
|
6
6
|
* @copyright 2019-2022 By Masashi Yoshikawa All rights reserved.
|
|
7
7
|
* @license MIT
|
|
8
|
-
* @version 1.1
|
|
8
|
+
* @version 1.2.1
|
|
9
9
|
* @see {@link https://github.com/logue/Reverb.js}
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { SYSTEM } from '@thi.ng/random';
|
|
13
|
+
import { white, violet, red, pink, green, blue } from '@thi.ng/colored-noise';
|
|
14
|
+
import { take } from '@thi.ng/transducers';
|
|
15
|
+
|
|
12
16
|
const Noise = {
|
|
13
17
|
BLUE: "blue",
|
|
14
18
|
GREEN: "green",
|
|
@@ -19,46 +23,6 @@ const Noise = {
|
|
|
19
23
|
BROWN: "red"
|
|
20
24
|
};
|
|
21
25
|
|
|
22
|
-
const INV_MAX = 1 / 2 ** 32;
|
|
23
|
-
class ARandom {
|
|
24
|
-
float(norm = 1) {
|
|
25
|
-
return this.int() * INV_MAX * norm;
|
|
26
|
-
}
|
|
27
|
-
norm(norm = 1) {
|
|
28
|
-
return (this.int() * INV_MAX - 0.5) * 2 * norm;
|
|
29
|
-
}
|
|
30
|
-
minmax(min, max) {
|
|
31
|
-
return this.float() * (max - min) + min;
|
|
32
|
-
}
|
|
33
|
-
minmaxInt(min, max) {
|
|
34
|
-
min |= 0;
|
|
35
|
-
max |= 0;
|
|
36
|
-
return min + ((this.float() * (max - min)) | 0);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const random = Math.random;
|
|
41
|
-
/**
|
|
42
|
-
* A `Math.random()` based {@link IRandom} implementation. Also @see
|
|
43
|
-
* {@link SYSTEM}.
|
|
44
|
-
*/
|
|
45
|
-
class SystemRandom extends ARandom {
|
|
46
|
-
int() {
|
|
47
|
-
return (random() * 4294967296) /* 2**32 */ >>> 0;
|
|
48
|
-
}
|
|
49
|
-
float(norm = 1) {
|
|
50
|
-
return random() * norm;
|
|
51
|
-
}
|
|
52
|
-
norm(norm = 1) {
|
|
53
|
-
return (random() - 0.5) * 2 * norm;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Used as default PRNG throughout most other thi.ng projects, though usually is
|
|
58
|
-
* configurable.
|
|
59
|
-
*/
|
|
60
|
-
const SYSTEM = new SystemRandom();
|
|
61
|
-
|
|
62
26
|
const defaults = {
|
|
63
27
|
noise: Noise.WHITE,
|
|
64
28
|
scale: 1,
|
|
@@ -76,245 +40,23 @@ const defaults = {
|
|
|
76
40
|
};
|
|
77
41
|
|
|
78
42
|
const meta = {
|
|
79
|
-
version: "1.1
|
|
80
|
-
date: "2022-11-
|
|
43
|
+
version: "1.2.1",
|
|
44
|
+
date: "2022-11-24T14:46:07.438Z"
|
|
81
45
|
};
|
|
82
46
|
|
|
83
|
-
const preseed = (n, scale, rnd) => {
|
|
84
|
-
const state = new Array(n);
|
|
85
|
-
for (let i = 0; i < n; i++) {
|
|
86
|
-
state[i] = rnd.norm(scale);
|
|
87
|
-
}
|
|
88
|
-
return state;
|
|
89
|
-
};
|
|
90
|
-
const sum = (src) => src.reduce((sum, x) => sum + x, 0);
|
|
91
|
-
function* interleave(a, b) {
|
|
92
|
-
const src = [a[Symbol.iterator](), b[Symbol.iterator]()];
|
|
93
|
-
for (let i = 0; true; i ^= 1) {
|
|
94
|
-
const next = src[i].next();
|
|
95
|
-
if (next.done)
|
|
96
|
-
return;
|
|
97
|
-
yield next.value;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* High-pass filtered noise. Opposite of {@link red}.
|
|
103
|
-
*
|
|
104
|
-
* @param n -
|
|
105
|
-
* @param scale -
|
|
106
|
-
* @param rnd -
|
|
107
|
-
*/
|
|
108
|
-
function* blue(n = 2, scale = 1, rnd = SYSTEM) {
|
|
109
|
-
const state = preseed(n, scale, rnd);
|
|
110
|
-
state.forEach((x, i) => (state[i] = i & 1 ? x : -x));
|
|
111
|
-
const invN = 1 / n;
|
|
112
|
-
let acc = sum(state);
|
|
113
|
-
for (let i = 0, sign = -1; true; ++i >= n && (i = 0)) {
|
|
114
|
-
acc -= state[i];
|
|
115
|
-
acc += state[i] = sign * rnd.norm(scale);
|
|
116
|
-
sign ^= 0xfffffffe;
|
|
117
|
-
yield sign * acc * invN;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Band-pass filtered noise (interleaved blue noise). Opposite of
|
|
123
|
-
* {@link violet}.
|
|
124
|
-
*
|
|
125
|
-
* @param n -
|
|
126
|
-
* @param scale -
|
|
127
|
-
* @param rnd -
|
|
128
|
-
*/
|
|
129
|
-
const green = (n = 2, scale = 1, rnd = SYSTEM) => interleave(blue(n, scale, rnd), blue(n, scale, rnd));
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Returns number of 1 bits in `x`.
|
|
133
|
-
*
|
|
134
|
-
* @param x -
|
|
135
|
-
*/
|
|
136
|
-
const ctz32 = (x) => {
|
|
137
|
-
let c = 32;
|
|
138
|
-
x &= -x;
|
|
139
|
-
x && c--;
|
|
140
|
-
x & 0x0000ffff && (c -= 16);
|
|
141
|
-
x & 0x00ff00ff && (c -= 8);
|
|
142
|
-
x & 0x0f0f0f0f && (c -= 4);
|
|
143
|
-
x & 0x33333333 && (c -= 2);
|
|
144
|
-
x & 0x55555555 && (c -= 1);
|
|
145
|
-
return c;
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Exponential decay (1/f) noise, based on Voss-McCarthy algorithm.
|
|
150
|
-
*
|
|
151
|
-
* @remarks
|
|
152
|
-
* The number of internal states should be in the [4..32] range (default: 8).
|
|
153
|
-
* Due to JS integer limitations, `n` > 32 are meaningless.
|
|
154
|
-
*
|
|
155
|
-
* References:
|
|
156
|
-
*
|
|
157
|
-
* - https://www.dsprelated.com/showarticle/908.php
|
|
158
|
-
* - https://www.firstpr.com.au/dsp/pink-noise/#Voss-McCartney
|
|
159
|
-
*
|
|
160
|
-
* @param n -
|
|
161
|
-
* @param scale -
|
|
162
|
-
* @param rnd -
|
|
163
|
-
*/
|
|
164
|
-
function* pink(n = 8, scale = 1, rnd = SYSTEM) {
|
|
165
|
-
const state = preseed(n, scale, rnd);
|
|
166
|
-
const invN = 1 / n;
|
|
167
|
-
let acc = sum(state);
|
|
168
|
-
for (let i = 0; true; i = (i + 1) >>> 0) {
|
|
169
|
-
const id = ctz32(i) % n;
|
|
170
|
-
acc -= state[id];
|
|
171
|
-
acc += state[id] = rnd.norm(scale);
|
|
172
|
-
yield acc * invN;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Low-pass filtered noise (same as brown noise). Opposite of {@link blue}.
|
|
178
|
-
*
|
|
179
|
-
* @param n -
|
|
180
|
-
* @param scale -
|
|
181
|
-
* @param rnd -
|
|
182
|
-
*/
|
|
183
|
-
function* red(n = 2, scale = 1, rnd = SYSTEM) {
|
|
184
|
-
const state = preseed(n, scale, rnd);
|
|
185
|
-
const invN = 1 / n;
|
|
186
|
-
let acc = sum(state);
|
|
187
|
-
for (let i = 0; true; ++i >= n && (i = 0)) {
|
|
188
|
-
acc -= state[i];
|
|
189
|
-
acc += state[i] = rnd.norm(scale);
|
|
190
|
-
yield acc * invN;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Band-stop filtered noise (interleaved red noise). Opposite of {@link green}.
|
|
196
|
-
*
|
|
197
|
-
* @param n -
|
|
198
|
-
* @param scale -
|
|
199
|
-
* @param rnd -
|
|
200
|
-
*/
|
|
201
|
-
const violet = (n = 2, scale = 1, rnd = SYSTEM) => interleave(red(n, scale, rnd), red(n, scale, rnd));
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Unfiltered noise w/ uniform distribution. Merely yields samples from
|
|
205
|
-
* given PRNG.
|
|
206
|
-
*
|
|
207
|
-
* @param scale -
|
|
208
|
-
* @param rnd -
|
|
209
|
-
*/
|
|
210
|
-
function* white(scale = 1, rnd = SYSTEM) {
|
|
211
|
-
while (true) {
|
|
212
|
-
yield rnd.norm(scale);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const implementsFunction = (x, fn) => x != null && typeof x[fn] === "function";
|
|
217
|
-
|
|
218
|
-
const ensureTransducer = (x) => implementsFunction(x, "xform") ? x.xform() : x;
|
|
219
|
-
|
|
220
|
-
const isIterable = (x) => x != null && typeof x[Symbol.iterator] === "function";
|
|
221
|
-
|
|
222
|
-
class Reduced {
|
|
223
|
-
constructor(val) {
|
|
224
|
-
this.value = val;
|
|
225
|
-
}
|
|
226
|
-
deref() {
|
|
227
|
-
return this.value;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
const reduced = (x) => new Reduced(x);
|
|
231
|
-
const isReduced = (x) => x instanceof Reduced;
|
|
232
|
-
const ensureReduced = (x) => x instanceof Reduced ? x : new Reduced(x);
|
|
233
|
-
const unreduced = (x) => (x instanceof Reduced ? x.deref() : x);
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Convenience helper for building a full {@link Reducer} using the identity
|
|
237
|
-
* function (i.e. `(x) => x`) as completion step (true for 90% of all
|
|
238
|
-
* bundled transducers).
|
|
239
|
-
*
|
|
240
|
-
* @param init - init step of reducer
|
|
241
|
-
* @param rfn - reduction step of reducer
|
|
242
|
-
*/
|
|
243
|
-
const reducer = (init, rfn) => [init, (acc) => acc, rfn];
|
|
244
|
-
|
|
245
|
-
function push(xs) {
|
|
246
|
-
return xs
|
|
247
|
-
? [...xs]
|
|
248
|
-
: reducer(() => [], (acc, x) => (acc.push(x), acc));
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Takes a transducer and input iterable. Returns iterator of
|
|
253
|
-
* transformed results.
|
|
254
|
-
*
|
|
255
|
-
* @param xform -
|
|
256
|
-
* @param xs -
|
|
257
|
-
*/
|
|
258
|
-
function* iterator(xform, xs) {
|
|
259
|
-
const rfn = ensureTransducer(xform)(push());
|
|
260
|
-
const complete = rfn[1];
|
|
261
|
-
const reduce = rfn[2];
|
|
262
|
-
for (let x of xs) {
|
|
263
|
-
const y = reduce([], x);
|
|
264
|
-
if (isReduced(y)) {
|
|
265
|
-
yield* unreduced(complete(y.deref()));
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
if (y.length) {
|
|
269
|
-
yield* y;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
yield* unreduced(complete([]));
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Reducer composition helper, internally used by various transducers
|
|
277
|
-
* during initialization. Takes existing reducer `rfn` (a 3-tuple) and a
|
|
278
|
-
* reducing function `fn`. Returns a new reducer tuple.
|
|
279
|
-
*
|
|
280
|
-
* @remarks
|
|
281
|
-
* `rfn[2]` reduces values of type `B` into an accumulator of type `A`.
|
|
282
|
-
* `fn` accepts values of type `C` and produces interim results of type
|
|
283
|
-
* `B`, which are then (possibly) passed to the "inner" `rfn[2]`
|
|
284
|
-
* function. Therefore the resulting reducer takes inputs of `C` and an
|
|
285
|
-
* accumulator of type `A`.
|
|
286
|
-
*
|
|
287
|
-
* It is assumed that `fn` internally calls `rfn[2]` to pass its own
|
|
288
|
-
* results for further processing by the nested reducer `rfn`.
|
|
289
|
-
*
|
|
290
|
-
* @example
|
|
291
|
-
* ```ts
|
|
292
|
-
* compR(rfn, fn)
|
|
293
|
-
* // [rfn[0], rfn[1], fn]
|
|
294
|
-
* ```
|
|
295
|
-
*
|
|
296
|
-
* @param rfn -
|
|
297
|
-
* @param fn -
|
|
298
|
-
*/
|
|
299
|
-
const compR = (rfn, fn) => [rfn[0], rfn[1], fn];
|
|
300
|
-
|
|
301
|
-
function take(n, src) {
|
|
302
|
-
return isIterable(src)
|
|
303
|
-
? iterator(take(n), src)
|
|
304
|
-
: (rfn) => {
|
|
305
|
-
const r = rfn[2];
|
|
306
|
-
let m = n;
|
|
307
|
-
return compR(rfn, (acc, x) => --m > 0
|
|
308
|
-
? r(acc, x)
|
|
309
|
-
: m === 0
|
|
310
|
-
? ensureReduced(r(acc, x))
|
|
311
|
-
: reduced(acc));
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
|
|
315
47
|
class Reverb {
|
|
48
|
+
static version = meta.version;
|
|
49
|
+
static build = meta.date;
|
|
50
|
+
ctx;
|
|
51
|
+
wetGainNode;
|
|
52
|
+
dryGainNode;
|
|
53
|
+
filterNode;
|
|
54
|
+
convolverNode;
|
|
55
|
+
outputNode;
|
|
56
|
+
options;
|
|
57
|
+
isConnected;
|
|
58
|
+
noise = white;
|
|
316
59
|
constructor(ctx, options) {
|
|
317
|
-
this.noise = white;
|
|
318
60
|
this.ctx = ctx;
|
|
319
61
|
this.options = { ...defaults, ...options };
|
|
320
62
|
this.wetGainNode = this.ctx.createGain();
|
|
@@ -481,7 +223,7 @@ class Reverb {
|
|
|
481
223
|
return [
|
|
482
224
|
...take(
|
|
483
225
|
duration,
|
|
484
|
-
this.noise
|
|
226
|
+
this.noise(
|
|
485
227
|
this.options.peaks,
|
|
486
228
|
this.options.scale,
|
|
487
229
|
this.options.randomAlgorithm
|
|
@@ -490,8 +232,6 @@ class Reverb {
|
|
|
490
232
|
];
|
|
491
233
|
}
|
|
492
234
|
}
|
|
493
|
-
Reverb.version = meta.version;
|
|
494
|
-
Reverb.build = meta.date;
|
|
495
235
|
if (!window.Reverb) {
|
|
496
236
|
window.Reverb = Reverb;
|
|
497
237
|
}
|
package/dist/Reverb.iife.js
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
* @author Logue <logue@hotmail.co.jp>
|
|
6
6
|
* @copyright 2019-2022 By Masashi Yoshikawa All rights reserved.
|
|
7
7
|
* @license MIT
|
|
8
|
-
* @version 1.1
|
|
8
|
+
* @version 1.2.1
|
|
9
9
|
* @see {@link https://github.com/logue/Reverb.js}
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
var Reverb = (function (
|
|
12
|
+
var Reverb = (function (random, coloredNoise, transducers) {
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
15
|
const Noise = {
|
|
@@ -22,51 +22,11 @@ var Reverb = (function (exports) {
|
|
|
22
22
|
BROWN: "red"
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
const INV_MAX = 1 / 2 ** 32;
|
|
26
|
-
class ARandom {
|
|
27
|
-
float(norm = 1) {
|
|
28
|
-
return this.int() * INV_MAX * norm;
|
|
29
|
-
}
|
|
30
|
-
norm(norm = 1) {
|
|
31
|
-
return (this.int() * INV_MAX - 0.5) * 2 * norm;
|
|
32
|
-
}
|
|
33
|
-
minmax(min, max) {
|
|
34
|
-
return this.float() * (max - min) + min;
|
|
35
|
-
}
|
|
36
|
-
minmaxInt(min, max) {
|
|
37
|
-
min |= 0;
|
|
38
|
-
max |= 0;
|
|
39
|
-
return min + ((this.float() * (max - min)) | 0);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const random = Math.random;
|
|
44
|
-
/**
|
|
45
|
-
* A `Math.random()` based {@link IRandom} implementation. Also @see
|
|
46
|
-
* {@link SYSTEM}.
|
|
47
|
-
*/
|
|
48
|
-
class SystemRandom extends ARandom {
|
|
49
|
-
int() {
|
|
50
|
-
return (random() * 4294967296) /* 2**32 */ >>> 0;
|
|
51
|
-
}
|
|
52
|
-
float(norm = 1) {
|
|
53
|
-
return random() * norm;
|
|
54
|
-
}
|
|
55
|
-
norm(norm = 1) {
|
|
56
|
-
return (random() - 0.5) * 2 * norm;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Used as default PRNG throughout most other thi.ng projects, though usually is
|
|
61
|
-
* configurable.
|
|
62
|
-
*/
|
|
63
|
-
const SYSTEM = new SystemRandom();
|
|
64
|
-
|
|
65
25
|
const defaults = {
|
|
66
26
|
noise: Noise.WHITE,
|
|
67
27
|
scale: 1,
|
|
68
28
|
peaks: 2,
|
|
69
|
-
randomAlgorithm: SYSTEM,
|
|
29
|
+
randomAlgorithm: random.SYSTEM,
|
|
70
30
|
decay: 2,
|
|
71
31
|
delay: 0,
|
|
72
32
|
reverse: false,
|
|
@@ -79,245 +39,23 @@ var Reverb = (function (exports) {
|
|
|
79
39
|
};
|
|
80
40
|
|
|
81
41
|
const meta = {
|
|
82
|
-
version: "1.1
|
|
83
|
-
date: "2022-11-
|
|
42
|
+
version: "1.2.1",
|
|
43
|
+
date: "2022-11-24T14:46:07.438Z"
|
|
84
44
|
};
|
|
85
45
|
|
|
86
|
-
const preseed = (n, scale, rnd) => {
|
|
87
|
-
const state = new Array(n);
|
|
88
|
-
for (let i = 0; i < n; i++) {
|
|
89
|
-
state[i] = rnd.norm(scale);
|
|
90
|
-
}
|
|
91
|
-
return state;
|
|
92
|
-
};
|
|
93
|
-
const sum = (src) => src.reduce((sum, x) => sum + x, 0);
|
|
94
|
-
function* interleave(a, b) {
|
|
95
|
-
const src = [a[Symbol.iterator](), b[Symbol.iterator]()];
|
|
96
|
-
for (let i = 0; true; i ^= 1) {
|
|
97
|
-
const next = src[i].next();
|
|
98
|
-
if (next.done)
|
|
99
|
-
return;
|
|
100
|
-
yield next.value;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* High-pass filtered noise. Opposite of {@link red}.
|
|
106
|
-
*
|
|
107
|
-
* @param n -
|
|
108
|
-
* @param scale -
|
|
109
|
-
* @param rnd -
|
|
110
|
-
*/
|
|
111
|
-
function* blue(n = 2, scale = 1, rnd = SYSTEM) {
|
|
112
|
-
const state = preseed(n, scale, rnd);
|
|
113
|
-
state.forEach((x, i) => (state[i] = i & 1 ? x : -x));
|
|
114
|
-
const invN = 1 / n;
|
|
115
|
-
let acc = sum(state);
|
|
116
|
-
for (let i = 0, sign = -1; true; ++i >= n && (i = 0)) {
|
|
117
|
-
acc -= state[i];
|
|
118
|
-
acc += state[i] = sign * rnd.norm(scale);
|
|
119
|
-
sign ^= 0xfffffffe;
|
|
120
|
-
yield sign * acc * invN;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Band-pass filtered noise (interleaved blue noise). Opposite of
|
|
126
|
-
* {@link violet}.
|
|
127
|
-
*
|
|
128
|
-
* @param n -
|
|
129
|
-
* @param scale -
|
|
130
|
-
* @param rnd -
|
|
131
|
-
*/
|
|
132
|
-
const green = (n = 2, scale = 1, rnd = SYSTEM) => interleave(blue(n, scale, rnd), blue(n, scale, rnd));
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Returns number of 1 bits in `x`.
|
|
136
|
-
*
|
|
137
|
-
* @param x -
|
|
138
|
-
*/
|
|
139
|
-
const ctz32 = (x) => {
|
|
140
|
-
let c = 32;
|
|
141
|
-
x &= -x;
|
|
142
|
-
x && c--;
|
|
143
|
-
x & 0x0000ffff && (c -= 16);
|
|
144
|
-
x & 0x00ff00ff && (c -= 8);
|
|
145
|
-
x & 0x0f0f0f0f && (c -= 4);
|
|
146
|
-
x & 0x33333333 && (c -= 2);
|
|
147
|
-
x & 0x55555555 && (c -= 1);
|
|
148
|
-
return c;
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Exponential decay (1/f) noise, based on Voss-McCarthy algorithm.
|
|
153
|
-
*
|
|
154
|
-
* @remarks
|
|
155
|
-
* The number of internal states should be in the [4..32] range (default: 8).
|
|
156
|
-
* Due to JS integer limitations, `n` > 32 are meaningless.
|
|
157
|
-
*
|
|
158
|
-
* References:
|
|
159
|
-
*
|
|
160
|
-
* - https://www.dsprelated.com/showarticle/908.php
|
|
161
|
-
* - https://www.firstpr.com.au/dsp/pink-noise/#Voss-McCartney
|
|
162
|
-
*
|
|
163
|
-
* @param n -
|
|
164
|
-
* @param scale -
|
|
165
|
-
* @param rnd -
|
|
166
|
-
*/
|
|
167
|
-
function* pink(n = 8, scale = 1, rnd = SYSTEM) {
|
|
168
|
-
const state = preseed(n, scale, rnd);
|
|
169
|
-
const invN = 1 / n;
|
|
170
|
-
let acc = sum(state);
|
|
171
|
-
for (let i = 0; true; i = (i + 1) >>> 0) {
|
|
172
|
-
const id = ctz32(i) % n;
|
|
173
|
-
acc -= state[id];
|
|
174
|
-
acc += state[id] = rnd.norm(scale);
|
|
175
|
-
yield acc * invN;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Low-pass filtered noise (same as brown noise). Opposite of {@link blue}.
|
|
181
|
-
*
|
|
182
|
-
* @param n -
|
|
183
|
-
* @param scale -
|
|
184
|
-
* @param rnd -
|
|
185
|
-
*/
|
|
186
|
-
function* red(n = 2, scale = 1, rnd = SYSTEM) {
|
|
187
|
-
const state = preseed(n, scale, rnd);
|
|
188
|
-
const invN = 1 / n;
|
|
189
|
-
let acc = sum(state);
|
|
190
|
-
for (let i = 0; true; ++i >= n && (i = 0)) {
|
|
191
|
-
acc -= state[i];
|
|
192
|
-
acc += state[i] = rnd.norm(scale);
|
|
193
|
-
yield acc * invN;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Band-stop filtered noise (interleaved red noise). Opposite of {@link green}.
|
|
199
|
-
*
|
|
200
|
-
* @param n -
|
|
201
|
-
* @param scale -
|
|
202
|
-
* @param rnd -
|
|
203
|
-
*/
|
|
204
|
-
const violet = (n = 2, scale = 1, rnd = SYSTEM) => interleave(red(n, scale, rnd), red(n, scale, rnd));
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Unfiltered noise w/ uniform distribution. Merely yields samples from
|
|
208
|
-
* given PRNG.
|
|
209
|
-
*
|
|
210
|
-
* @param scale -
|
|
211
|
-
* @param rnd -
|
|
212
|
-
*/
|
|
213
|
-
function* white(scale = 1, rnd = SYSTEM) {
|
|
214
|
-
while (true) {
|
|
215
|
-
yield rnd.norm(scale);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const implementsFunction = (x, fn) => x != null && typeof x[fn] === "function";
|
|
220
|
-
|
|
221
|
-
const ensureTransducer = (x) => implementsFunction(x, "xform") ? x.xform() : x;
|
|
222
|
-
|
|
223
|
-
const isIterable = (x) => x != null && typeof x[Symbol.iterator] === "function";
|
|
224
|
-
|
|
225
|
-
class Reduced {
|
|
226
|
-
constructor(val) {
|
|
227
|
-
this.value = val;
|
|
228
|
-
}
|
|
229
|
-
deref() {
|
|
230
|
-
return this.value;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
const reduced = (x) => new Reduced(x);
|
|
234
|
-
const isReduced = (x) => x instanceof Reduced;
|
|
235
|
-
const ensureReduced = (x) => x instanceof Reduced ? x : new Reduced(x);
|
|
236
|
-
const unreduced = (x) => (x instanceof Reduced ? x.deref() : x);
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Convenience helper for building a full {@link Reducer} using the identity
|
|
240
|
-
* function (i.e. `(x) => x`) as completion step (true for 90% of all
|
|
241
|
-
* bundled transducers).
|
|
242
|
-
*
|
|
243
|
-
* @param init - init step of reducer
|
|
244
|
-
* @param rfn - reduction step of reducer
|
|
245
|
-
*/
|
|
246
|
-
const reducer = (init, rfn) => [init, (acc) => acc, rfn];
|
|
247
|
-
|
|
248
|
-
function push(xs) {
|
|
249
|
-
return xs
|
|
250
|
-
? [...xs]
|
|
251
|
-
: reducer(() => [], (acc, x) => (acc.push(x), acc));
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Takes a transducer and input iterable. Returns iterator of
|
|
256
|
-
* transformed results.
|
|
257
|
-
*
|
|
258
|
-
* @param xform -
|
|
259
|
-
* @param xs -
|
|
260
|
-
*/
|
|
261
|
-
function* iterator(xform, xs) {
|
|
262
|
-
const rfn = ensureTransducer(xform)(push());
|
|
263
|
-
const complete = rfn[1];
|
|
264
|
-
const reduce = rfn[2];
|
|
265
|
-
for (let x of xs) {
|
|
266
|
-
const y = reduce([], x);
|
|
267
|
-
if (isReduced(y)) {
|
|
268
|
-
yield* unreduced(complete(y.deref()));
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
if (y.length) {
|
|
272
|
-
yield* y;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
yield* unreduced(complete([]));
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Reducer composition helper, internally used by various transducers
|
|
280
|
-
* during initialization. Takes existing reducer `rfn` (a 3-tuple) and a
|
|
281
|
-
* reducing function `fn`. Returns a new reducer tuple.
|
|
282
|
-
*
|
|
283
|
-
* @remarks
|
|
284
|
-
* `rfn[2]` reduces values of type `B` into an accumulator of type `A`.
|
|
285
|
-
* `fn` accepts values of type `C` and produces interim results of type
|
|
286
|
-
* `B`, which are then (possibly) passed to the "inner" `rfn[2]`
|
|
287
|
-
* function. Therefore the resulting reducer takes inputs of `C` and an
|
|
288
|
-
* accumulator of type `A`.
|
|
289
|
-
*
|
|
290
|
-
* It is assumed that `fn` internally calls `rfn[2]` to pass its own
|
|
291
|
-
* results for further processing by the nested reducer `rfn`.
|
|
292
|
-
*
|
|
293
|
-
* @example
|
|
294
|
-
* ```ts
|
|
295
|
-
* compR(rfn, fn)
|
|
296
|
-
* // [rfn[0], rfn[1], fn]
|
|
297
|
-
* ```
|
|
298
|
-
*
|
|
299
|
-
* @param rfn -
|
|
300
|
-
* @param fn -
|
|
301
|
-
*/
|
|
302
|
-
const compR = (rfn, fn) => [rfn[0], rfn[1], fn];
|
|
303
|
-
|
|
304
|
-
function take(n, src) {
|
|
305
|
-
return isIterable(src)
|
|
306
|
-
? iterator(take(n), src)
|
|
307
|
-
: (rfn) => {
|
|
308
|
-
const r = rfn[2];
|
|
309
|
-
let m = n;
|
|
310
|
-
return compR(rfn, (acc, x) => --m > 0
|
|
311
|
-
? r(acc, x)
|
|
312
|
-
: m === 0
|
|
313
|
-
? ensureReduced(r(acc, x))
|
|
314
|
-
: reduced(acc));
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
|
|
318
46
|
class Reverb {
|
|
47
|
+
static version = meta.version;
|
|
48
|
+
static build = meta.date;
|
|
49
|
+
ctx;
|
|
50
|
+
wetGainNode;
|
|
51
|
+
dryGainNode;
|
|
52
|
+
filterNode;
|
|
53
|
+
convolverNode;
|
|
54
|
+
outputNode;
|
|
55
|
+
options;
|
|
56
|
+
isConnected;
|
|
57
|
+
noise = coloredNoise.white;
|
|
319
58
|
constructor(ctx, options) {
|
|
320
|
-
this.noise = white;
|
|
321
59
|
this.ctx = ctx;
|
|
322
60
|
this.options = { ...defaults, ...options };
|
|
323
61
|
this.wetGainNode = this.ctx.createGain();
|
|
@@ -428,23 +166,23 @@ var Reverb = (function (exports) {
|
|
|
428
166
|
this.options.noise = type;
|
|
429
167
|
switch (type) {
|
|
430
168
|
case Noise.BLUE:
|
|
431
|
-
this.noise = blue;
|
|
169
|
+
this.noise = coloredNoise.blue;
|
|
432
170
|
break;
|
|
433
171
|
case Noise.GREEN:
|
|
434
|
-
this.noise = green;
|
|
172
|
+
this.noise = coloredNoise.green;
|
|
435
173
|
break;
|
|
436
174
|
case Noise.PINK:
|
|
437
|
-
this.noise = pink;
|
|
175
|
+
this.noise = coloredNoise.pink;
|
|
438
176
|
break;
|
|
439
177
|
case Noise.RED:
|
|
440
178
|
case Noise.BROWN:
|
|
441
|
-
this.noise = red;
|
|
179
|
+
this.noise = coloredNoise.red;
|
|
442
180
|
break;
|
|
443
181
|
case Noise.VIOLET:
|
|
444
|
-
this.noise = violet;
|
|
182
|
+
this.noise = coloredNoise.violet;
|
|
445
183
|
break;
|
|
446
184
|
default:
|
|
447
|
-
this.noise = white;
|
|
185
|
+
this.noise = coloredNoise.white;
|
|
448
186
|
}
|
|
449
187
|
this.buildImpulse();
|
|
450
188
|
}
|
|
@@ -482,9 +220,9 @@ var Reverb = (function (exports) {
|
|
|
482
220
|
}
|
|
483
221
|
getNoise(duration) {
|
|
484
222
|
return [
|
|
485
|
-
...take(
|
|
223
|
+
...transducers.take(
|
|
486
224
|
duration,
|
|
487
|
-
this.noise
|
|
225
|
+
this.noise(
|
|
488
226
|
this.options.peaks,
|
|
489
227
|
this.options.scale,
|
|
490
228
|
this.options.randomAlgorithm
|
|
@@ -493,16 +231,10 @@ var Reverb = (function (exports) {
|
|
|
493
231
|
];
|
|
494
232
|
}
|
|
495
233
|
}
|
|
496
|
-
Reverb.version = meta.version;
|
|
497
|
-
Reverb.build = meta.date;
|
|
498
234
|
if (!window.Reverb) {
|
|
499
235
|
window.Reverb = Reverb;
|
|
500
236
|
}
|
|
501
237
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
|
|
505
|
-
|
|
506
|
-
return exports;
|
|
238
|
+
return Reverb;
|
|
507
239
|
|
|
508
|
-
})(
|
|
240
|
+
})(random, colordNoise, transducers);
|
package/dist/Reverb.umd.js
CHANGED
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
* @author Logue <logue@hotmail.co.jp>
|
|
6
6
|
* @copyright 2019-2022 By Masashi Yoshikawa All rights reserved.
|
|
7
7
|
* @license MIT
|
|
8
|
-
* @version 1.1
|
|
8
|
+
* @version 1.2.1
|
|
9
9
|
* @see {@link https://github.com/logue/Reverb.js}
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
(function (global, factory) {
|
|
13
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(
|
|
14
|
-
typeof define === 'function' && define.amd ? define(['
|
|
15
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self,
|
|
16
|
-
})(this, (function (
|
|
13
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@thi.ng/random'), require('@thi.ng/colored-noise'), require('@thi.ng/transducers')) :
|
|
14
|
+
typeof define === 'function' && define.amd ? define(['@thi.ng/random', '@thi.ng/colored-noise', '@thi.ng/transducers'], factory) :
|
|
15
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Reverb = factory(global.random, global.colordNoise, global.transducers));
|
|
16
|
+
})(this, (function (random, coloredNoise, transducers) { 'use strict';
|
|
17
17
|
|
|
18
18
|
const Noise = {
|
|
19
19
|
BLUE: "blue",
|
|
@@ -25,51 +25,11 @@
|
|
|
25
25
|
BROWN: "red"
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const INV_MAX = 1 / 2 ** 32;
|
|
29
|
-
class ARandom {
|
|
30
|
-
float(norm = 1) {
|
|
31
|
-
return this.int() * INV_MAX * norm;
|
|
32
|
-
}
|
|
33
|
-
norm(norm = 1) {
|
|
34
|
-
return (this.int() * INV_MAX - 0.5) * 2 * norm;
|
|
35
|
-
}
|
|
36
|
-
minmax(min, max) {
|
|
37
|
-
return this.float() * (max - min) + min;
|
|
38
|
-
}
|
|
39
|
-
minmaxInt(min, max) {
|
|
40
|
-
min |= 0;
|
|
41
|
-
max |= 0;
|
|
42
|
-
return min + ((this.float() * (max - min)) | 0);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const random = Math.random;
|
|
47
|
-
/**
|
|
48
|
-
* A `Math.random()` based {@link IRandom} implementation. Also @see
|
|
49
|
-
* {@link SYSTEM}.
|
|
50
|
-
*/
|
|
51
|
-
class SystemRandom extends ARandom {
|
|
52
|
-
int() {
|
|
53
|
-
return (random() * 4294967296) /* 2**32 */ >>> 0;
|
|
54
|
-
}
|
|
55
|
-
float(norm = 1) {
|
|
56
|
-
return random() * norm;
|
|
57
|
-
}
|
|
58
|
-
norm(norm = 1) {
|
|
59
|
-
return (random() - 0.5) * 2 * norm;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Used as default PRNG throughout most other thi.ng projects, though usually is
|
|
64
|
-
* configurable.
|
|
65
|
-
*/
|
|
66
|
-
const SYSTEM = new SystemRandom();
|
|
67
|
-
|
|
68
28
|
const defaults = {
|
|
69
29
|
noise: Noise.WHITE,
|
|
70
30
|
scale: 1,
|
|
71
31
|
peaks: 2,
|
|
72
|
-
randomAlgorithm: SYSTEM,
|
|
32
|
+
randomAlgorithm: random.SYSTEM,
|
|
73
33
|
decay: 2,
|
|
74
34
|
delay: 0,
|
|
75
35
|
reverse: false,
|
|
@@ -82,245 +42,23 @@
|
|
|
82
42
|
};
|
|
83
43
|
|
|
84
44
|
const meta = {
|
|
85
|
-
version: "1.1
|
|
86
|
-
date: "2022-11-
|
|
45
|
+
version: "1.2.1",
|
|
46
|
+
date: "2022-11-24T14:46:07.438Z"
|
|
87
47
|
};
|
|
88
48
|
|
|
89
|
-
const preseed = (n, scale, rnd) => {
|
|
90
|
-
const state = new Array(n);
|
|
91
|
-
for (let i = 0; i < n; i++) {
|
|
92
|
-
state[i] = rnd.norm(scale);
|
|
93
|
-
}
|
|
94
|
-
return state;
|
|
95
|
-
};
|
|
96
|
-
const sum = (src) => src.reduce((sum, x) => sum + x, 0);
|
|
97
|
-
function* interleave(a, b) {
|
|
98
|
-
const src = [a[Symbol.iterator](), b[Symbol.iterator]()];
|
|
99
|
-
for (let i = 0; true; i ^= 1) {
|
|
100
|
-
const next = src[i].next();
|
|
101
|
-
if (next.done)
|
|
102
|
-
return;
|
|
103
|
-
yield next.value;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* High-pass filtered noise. Opposite of {@link red}.
|
|
109
|
-
*
|
|
110
|
-
* @param n -
|
|
111
|
-
* @param scale -
|
|
112
|
-
* @param rnd -
|
|
113
|
-
*/
|
|
114
|
-
function* blue(n = 2, scale = 1, rnd = SYSTEM) {
|
|
115
|
-
const state = preseed(n, scale, rnd);
|
|
116
|
-
state.forEach((x, i) => (state[i] = i & 1 ? x : -x));
|
|
117
|
-
const invN = 1 / n;
|
|
118
|
-
let acc = sum(state);
|
|
119
|
-
for (let i = 0, sign = -1; true; ++i >= n && (i = 0)) {
|
|
120
|
-
acc -= state[i];
|
|
121
|
-
acc += state[i] = sign * rnd.norm(scale);
|
|
122
|
-
sign ^= 0xfffffffe;
|
|
123
|
-
yield sign * acc * invN;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Band-pass filtered noise (interleaved blue noise). Opposite of
|
|
129
|
-
* {@link violet}.
|
|
130
|
-
*
|
|
131
|
-
* @param n -
|
|
132
|
-
* @param scale -
|
|
133
|
-
* @param rnd -
|
|
134
|
-
*/
|
|
135
|
-
const green = (n = 2, scale = 1, rnd = SYSTEM) => interleave(blue(n, scale, rnd), blue(n, scale, rnd));
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Returns number of 1 bits in `x`.
|
|
139
|
-
*
|
|
140
|
-
* @param x -
|
|
141
|
-
*/
|
|
142
|
-
const ctz32 = (x) => {
|
|
143
|
-
let c = 32;
|
|
144
|
-
x &= -x;
|
|
145
|
-
x && c--;
|
|
146
|
-
x & 0x0000ffff && (c -= 16);
|
|
147
|
-
x & 0x00ff00ff && (c -= 8);
|
|
148
|
-
x & 0x0f0f0f0f && (c -= 4);
|
|
149
|
-
x & 0x33333333 && (c -= 2);
|
|
150
|
-
x & 0x55555555 && (c -= 1);
|
|
151
|
-
return c;
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Exponential decay (1/f) noise, based on Voss-McCarthy algorithm.
|
|
156
|
-
*
|
|
157
|
-
* @remarks
|
|
158
|
-
* The number of internal states should be in the [4..32] range (default: 8).
|
|
159
|
-
* Due to JS integer limitations, `n` > 32 are meaningless.
|
|
160
|
-
*
|
|
161
|
-
* References:
|
|
162
|
-
*
|
|
163
|
-
* - https://www.dsprelated.com/showarticle/908.php
|
|
164
|
-
* - https://www.firstpr.com.au/dsp/pink-noise/#Voss-McCartney
|
|
165
|
-
*
|
|
166
|
-
* @param n -
|
|
167
|
-
* @param scale -
|
|
168
|
-
* @param rnd -
|
|
169
|
-
*/
|
|
170
|
-
function* pink(n = 8, scale = 1, rnd = SYSTEM) {
|
|
171
|
-
const state = preseed(n, scale, rnd);
|
|
172
|
-
const invN = 1 / n;
|
|
173
|
-
let acc = sum(state);
|
|
174
|
-
for (let i = 0; true; i = (i + 1) >>> 0) {
|
|
175
|
-
const id = ctz32(i) % n;
|
|
176
|
-
acc -= state[id];
|
|
177
|
-
acc += state[id] = rnd.norm(scale);
|
|
178
|
-
yield acc * invN;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Low-pass filtered noise (same as brown noise). Opposite of {@link blue}.
|
|
184
|
-
*
|
|
185
|
-
* @param n -
|
|
186
|
-
* @param scale -
|
|
187
|
-
* @param rnd -
|
|
188
|
-
*/
|
|
189
|
-
function* red(n = 2, scale = 1, rnd = SYSTEM) {
|
|
190
|
-
const state = preseed(n, scale, rnd);
|
|
191
|
-
const invN = 1 / n;
|
|
192
|
-
let acc = sum(state);
|
|
193
|
-
for (let i = 0; true; ++i >= n && (i = 0)) {
|
|
194
|
-
acc -= state[i];
|
|
195
|
-
acc += state[i] = rnd.norm(scale);
|
|
196
|
-
yield acc * invN;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Band-stop filtered noise (interleaved red noise). Opposite of {@link green}.
|
|
202
|
-
*
|
|
203
|
-
* @param n -
|
|
204
|
-
* @param scale -
|
|
205
|
-
* @param rnd -
|
|
206
|
-
*/
|
|
207
|
-
const violet = (n = 2, scale = 1, rnd = SYSTEM) => interleave(red(n, scale, rnd), red(n, scale, rnd));
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Unfiltered noise w/ uniform distribution. Merely yields samples from
|
|
211
|
-
* given PRNG.
|
|
212
|
-
*
|
|
213
|
-
* @param scale -
|
|
214
|
-
* @param rnd -
|
|
215
|
-
*/
|
|
216
|
-
function* white(scale = 1, rnd = SYSTEM) {
|
|
217
|
-
while (true) {
|
|
218
|
-
yield rnd.norm(scale);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const implementsFunction = (x, fn) => x != null && typeof x[fn] === "function";
|
|
223
|
-
|
|
224
|
-
const ensureTransducer = (x) => implementsFunction(x, "xform") ? x.xform() : x;
|
|
225
|
-
|
|
226
|
-
const isIterable = (x) => x != null && typeof x[Symbol.iterator] === "function";
|
|
227
|
-
|
|
228
|
-
class Reduced {
|
|
229
|
-
constructor(val) {
|
|
230
|
-
this.value = val;
|
|
231
|
-
}
|
|
232
|
-
deref() {
|
|
233
|
-
return this.value;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
const reduced = (x) => new Reduced(x);
|
|
237
|
-
const isReduced = (x) => x instanceof Reduced;
|
|
238
|
-
const ensureReduced = (x) => x instanceof Reduced ? x : new Reduced(x);
|
|
239
|
-
const unreduced = (x) => (x instanceof Reduced ? x.deref() : x);
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Convenience helper for building a full {@link Reducer} using the identity
|
|
243
|
-
* function (i.e. `(x) => x`) as completion step (true for 90% of all
|
|
244
|
-
* bundled transducers).
|
|
245
|
-
*
|
|
246
|
-
* @param init - init step of reducer
|
|
247
|
-
* @param rfn - reduction step of reducer
|
|
248
|
-
*/
|
|
249
|
-
const reducer = (init, rfn) => [init, (acc) => acc, rfn];
|
|
250
|
-
|
|
251
|
-
function push(xs) {
|
|
252
|
-
return xs
|
|
253
|
-
? [...xs]
|
|
254
|
-
: reducer(() => [], (acc, x) => (acc.push(x), acc));
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Takes a transducer and input iterable. Returns iterator of
|
|
259
|
-
* transformed results.
|
|
260
|
-
*
|
|
261
|
-
* @param xform -
|
|
262
|
-
* @param xs -
|
|
263
|
-
*/
|
|
264
|
-
function* iterator(xform, xs) {
|
|
265
|
-
const rfn = ensureTransducer(xform)(push());
|
|
266
|
-
const complete = rfn[1];
|
|
267
|
-
const reduce = rfn[2];
|
|
268
|
-
for (let x of xs) {
|
|
269
|
-
const y = reduce([], x);
|
|
270
|
-
if (isReduced(y)) {
|
|
271
|
-
yield* unreduced(complete(y.deref()));
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
if (y.length) {
|
|
275
|
-
yield* y;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
yield* unreduced(complete([]));
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Reducer composition helper, internally used by various transducers
|
|
283
|
-
* during initialization. Takes existing reducer `rfn` (a 3-tuple) and a
|
|
284
|
-
* reducing function `fn`. Returns a new reducer tuple.
|
|
285
|
-
*
|
|
286
|
-
* @remarks
|
|
287
|
-
* `rfn[2]` reduces values of type `B` into an accumulator of type `A`.
|
|
288
|
-
* `fn` accepts values of type `C` and produces interim results of type
|
|
289
|
-
* `B`, which are then (possibly) passed to the "inner" `rfn[2]`
|
|
290
|
-
* function. Therefore the resulting reducer takes inputs of `C` and an
|
|
291
|
-
* accumulator of type `A`.
|
|
292
|
-
*
|
|
293
|
-
* It is assumed that `fn` internally calls `rfn[2]` to pass its own
|
|
294
|
-
* results for further processing by the nested reducer `rfn`.
|
|
295
|
-
*
|
|
296
|
-
* @example
|
|
297
|
-
* ```ts
|
|
298
|
-
* compR(rfn, fn)
|
|
299
|
-
* // [rfn[0], rfn[1], fn]
|
|
300
|
-
* ```
|
|
301
|
-
*
|
|
302
|
-
* @param rfn -
|
|
303
|
-
* @param fn -
|
|
304
|
-
*/
|
|
305
|
-
const compR = (rfn, fn) => [rfn[0], rfn[1], fn];
|
|
306
|
-
|
|
307
|
-
function take(n, src) {
|
|
308
|
-
return isIterable(src)
|
|
309
|
-
? iterator(take(n), src)
|
|
310
|
-
: (rfn) => {
|
|
311
|
-
const r = rfn[2];
|
|
312
|
-
let m = n;
|
|
313
|
-
return compR(rfn, (acc, x) => --m > 0
|
|
314
|
-
? r(acc, x)
|
|
315
|
-
: m === 0
|
|
316
|
-
? ensureReduced(r(acc, x))
|
|
317
|
-
: reduced(acc));
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
|
|
321
49
|
class Reverb {
|
|
50
|
+
static version = meta.version;
|
|
51
|
+
static build = meta.date;
|
|
52
|
+
ctx;
|
|
53
|
+
wetGainNode;
|
|
54
|
+
dryGainNode;
|
|
55
|
+
filterNode;
|
|
56
|
+
convolverNode;
|
|
57
|
+
outputNode;
|
|
58
|
+
options;
|
|
59
|
+
isConnected;
|
|
60
|
+
noise = coloredNoise.white;
|
|
322
61
|
constructor(ctx, options) {
|
|
323
|
-
this.noise = white;
|
|
324
62
|
this.ctx = ctx;
|
|
325
63
|
this.options = { ...defaults, ...options };
|
|
326
64
|
this.wetGainNode = this.ctx.createGain();
|
|
@@ -431,23 +169,23 @@
|
|
|
431
169
|
this.options.noise = type;
|
|
432
170
|
switch (type) {
|
|
433
171
|
case Noise.BLUE:
|
|
434
|
-
this.noise = blue;
|
|
172
|
+
this.noise = coloredNoise.blue;
|
|
435
173
|
break;
|
|
436
174
|
case Noise.GREEN:
|
|
437
|
-
this.noise = green;
|
|
175
|
+
this.noise = coloredNoise.green;
|
|
438
176
|
break;
|
|
439
177
|
case Noise.PINK:
|
|
440
|
-
this.noise = pink;
|
|
178
|
+
this.noise = coloredNoise.pink;
|
|
441
179
|
break;
|
|
442
180
|
case Noise.RED:
|
|
443
181
|
case Noise.BROWN:
|
|
444
|
-
this.noise = red;
|
|
182
|
+
this.noise = coloredNoise.red;
|
|
445
183
|
break;
|
|
446
184
|
case Noise.VIOLET:
|
|
447
|
-
this.noise = violet;
|
|
185
|
+
this.noise = coloredNoise.violet;
|
|
448
186
|
break;
|
|
449
187
|
default:
|
|
450
|
-
this.noise = white;
|
|
188
|
+
this.noise = coloredNoise.white;
|
|
451
189
|
}
|
|
452
190
|
this.buildImpulse();
|
|
453
191
|
}
|
|
@@ -485,9 +223,9 @@
|
|
|
485
223
|
}
|
|
486
224
|
getNoise(duration) {
|
|
487
225
|
return [
|
|
488
|
-
...take(
|
|
226
|
+
...transducers.take(
|
|
489
227
|
duration,
|
|
490
|
-
this.noise
|
|
228
|
+
this.noise(
|
|
491
229
|
this.options.peaks,
|
|
492
230
|
this.options.scale,
|
|
493
231
|
this.options.randomAlgorithm
|
|
@@ -496,14 +234,10 @@
|
|
|
496
234
|
];
|
|
497
235
|
}
|
|
498
236
|
}
|
|
499
|
-
Reverb.version = meta.version;
|
|
500
|
-
Reverb.build = meta.date;
|
|
501
237
|
if (!window.Reverb) {
|
|
502
238
|
window.Reverb = Reverb;
|
|
503
239
|
}
|
|
504
240
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
|
|
241
|
+
return Reverb;
|
|
508
242
|
|
|
509
243
|
}));
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@logue/reverb",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.1",
|
|
5
5
|
"description": "JavaScript Reverb effect class",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"webaudio",
|
|
@@ -37,28 +37,30 @@
|
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
|
-
"node": ">=
|
|
41
|
-
"yarn": ">=1.22.
|
|
40
|
+
"node": ">=18.12.1",
|
|
41
|
+
"yarn": ">=1.22.19"
|
|
42
42
|
},
|
|
43
|
-
"packageManager": "yarn@3.
|
|
43
|
+
"packageManager": "yarn@3.3.0",
|
|
44
44
|
"sideEffects": false,
|
|
45
45
|
"scripts": {
|
|
46
46
|
"dev": "vite",
|
|
47
|
-
"
|
|
48
|
-
"build
|
|
47
|
+
"type-check": "tsc --composite false",
|
|
48
|
+
"build": "vite build && tsc --noEmit false --declaration --emitDeclarationOnly",
|
|
49
|
+
"build:analyze": "vite build --mode analyze",
|
|
49
50
|
"build:clean": "rimraf dist",
|
|
50
51
|
"lint": "eslint . --fix --cache --cache-location ./node_modules/.vite/vite-plugin-eslint && prettier . --write",
|
|
52
|
+
"preview": "vite serve docs",
|
|
51
53
|
"prepare": "husky install"
|
|
52
54
|
},
|
|
53
55
|
"dependencies": {
|
|
54
|
-
"@thi.ng/colored-noise": "^0.
|
|
55
|
-
"@thi.ng/transducers": "^8.3.
|
|
56
|
+
"@thi.ng/colored-noise": "^1.0.0",
|
|
57
|
+
"@thi.ng/transducers": "^8.3.23"
|
|
56
58
|
},
|
|
57
59
|
"devDependencies": {
|
|
58
60
|
"@types/node": "^18.11.9",
|
|
59
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
60
|
-
"@typescript-eslint/parser": "^5.
|
|
61
|
-
"eslint": "^8.
|
|
61
|
+
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
|
62
|
+
"@typescript-eslint/parser": "^5.44.0",
|
|
63
|
+
"eslint": "^8.28.0",
|
|
62
64
|
"eslint-config-google": "^0.14.0",
|
|
63
65
|
"eslint-config-prettier": "^8.5.0",
|
|
64
66
|
"eslint-import-resolver-alias": "^1.1.2",
|
|
@@ -67,15 +69,16 @@
|
|
|
67
69
|
"eslint-plugin-jsdoc": "^39.6.2",
|
|
68
70
|
"eslint-plugin-prettier": "^4.2.1",
|
|
69
71
|
"eslint-plugin-tsdoc": "^0.2.17",
|
|
70
|
-
"husky": "^8.0.
|
|
72
|
+
"husky": "^8.0.2",
|
|
71
73
|
"lint-staged": "^13.0.3",
|
|
72
|
-
"prettier": "^2.
|
|
74
|
+
"prettier": "^2.8.0",
|
|
73
75
|
"rimraf": "^3.0.2",
|
|
74
76
|
"rollup-plugin-visualizer": "^5.8.3",
|
|
75
|
-
"typescript": "^4.
|
|
76
|
-
"vite": "^3.2.
|
|
77
|
+
"typescript": "^4.9.3",
|
|
78
|
+
"vite": "^3.2.4",
|
|
77
79
|
"vite-plugin-banner": "^0.6.1",
|
|
78
|
-
"vite-plugin-checker": "^0.5.1"
|
|
80
|
+
"vite-plugin-checker": "^0.5.1",
|
|
81
|
+
"vite-plugin-dts": "^1.7.1"
|
|
79
82
|
},
|
|
80
83
|
"husky": {
|
|
81
84
|
"hooks": {
|
|
@@ -87,6 +90,6 @@
|
|
|
87
90
|
"*": "prettier -w -u"
|
|
88
91
|
},
|
|
89
92
|
"resolutions": {
|
|
90
|
-
"prettier": "^2.
|
|
93
|
+
"prettier": "^2.8.0"
|
|
91
94
|
}
|
|
92
95
|
}
|