@audio/reverb-schroeder 1.0.0

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.
Files changed (2) hide show
  1. package/package.json +29 -0
  2. package/schroeder.js +51 -0
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@audio/reverb-schroeder",
3
+ "version": "1.0.0",
4
+ "description": "Schroeder reverb — 4 parallel feedback combs with LP damping + 2 series allpass diffusers",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "schroeder.js",
8
+ "exports": {
9
+ ".": "./schroeder.js",
10
+ "./package.json": "./package.json"
11
+ },
12
+ "files": [
13
+ "schroeder.js"
14
+ ],
15
+ "keywords": [
16
+ "audio",
17
+ "dsp",
18
+ "reverb",
19
+ "schroeder"
20
+ ],
21
+ "license": "MIT",
22
+ "author": "Dmitry Iv. <dfcreative@gmail.com>",
23
+ "engines": {
24
+ "node": ">=18"
25
+ },
26
+ "publishConfig": {
27
+ "access": "public"
28
+ }
29
+ }
package/schroeder.js ADDED
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Reverb — Schroeder reverb: parallel feedback comb filters + series allpass.
3
+ * 4 comb filters with LP damping, 2 allpass diffusers.
4
+ */
5
+
6
+ export default function reverb (data, params) {
7
+ let decay = params.decay ?? 0.84 // reverb time (0–1)
8
+ let damping = params.damping ?? 0.5 // high-freq damping (0–1)
9
+ let mix = params.mix ?? 0.3 // wet/dry mix
10
+ let fs = params.fs || 44100
11
+
12
+ let scale = fs / 44100
13
+
14
+ if (!params._c) {
15
+ // 4 prime comb delays (~29–35 ms at 44100 Hz)
16
+ let cl = [1277, 1381, 1447, 1523].map(n => (n * scale) | 0)
17
+ params._c = cl.map(n => ({ b: new Float64Array(n), p: 0, f: 0 }))
18
+ // 2 allpass delays (~6–8 ms at 44100 Hz)
19
+ let al = [277, 349].map(n => (n * scale) | 0)
20
+ params._a = al.map(n => ({ b: new Float64Array(n), p: 0 }))
21
+ }
22
+
23
+ let combs = params._c, aps = params._a
24
+
25
+ for (let i = 0, l = data.length; i < l; i++) {
26
+ let x = data[i]
27
+
28
+ // 4 parallel feedback comb filters with LP damping on feedback path
29
+ let out = 0
30
+ for (let c of combs) {
31
+ let y = c.b[c.p]
32
+ c.f = y * (1 - damping) + c.f * damping // one-pole LP
33
+ c.b[c.p] = x + decay * c.f
34
+ c.p = (c.p + 1) % c.b.length
35
+ out += y
36
+ }
37
+ out *= 0.25
38
+
39
+ // 2 series Schroeder allpass filters (g = 0.5)
40
+ for (let a of aps) {
41
+ let y = a.b[a.p]
42
+ a.b[a.p] = out + 0.5 * y
43
+ a.p = (a.p + 1) % a.b.length
44
+ out = y - 0.5 * out
45
+ }
46
+
47
+ data[i] = x * (1 - mix) + out * mix
48
+ }
49
+
50
+ return data
51
+ }