@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.
- package/package.json +29 -0
- 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
|
+
}
|