@audio/filter-resonator 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 +38 -0
  2. package/resonator.js +59 -0
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@audio/filter-resonator",
3
+ "version": "1.0.0",
4
+ "description": "Constant-peak-gain resonator (JOS two-zero form)",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "resonator.js",
8
+ "exports": {
9
+ ".": "./resonator.js",
10
+ "./package.json": "./package.json"
11
+ },
12
+ "files": [
13
+ "resonator.js"
14
+ ],
15
+ "keywords": [
16
+ "audio",
17
+ "dsp",
18
+ "filter",
19
+ "resonator"
20
+ ],
21
+ "license": "MIT",
22
+ "author": "Dmitry Iv. <dfcreative@gmail.com>",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/audiojs/filter.git",
26
+ "directory": "packages/filter-resonator"
27
+ },
28
+ "homepage": "https://github.com/audiojs/filter/tree/main/packages/filter-resonator",
29
+ "bugs": {
30
+ "url": "https://github.com/audiojs/filter/issues"
31
+ },
32
+ "engines": {
33
+ "node": ">=18"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ }
38
+ }
package/resonator.js ADDED
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Constant-peak-gain resonator (JOS two-zero form)
3
+ * Two zeros at z=±1 normalize the pole peak to exactly 1, regardless of fc/bw.
4
+ * Used for modal synthesis (bells, drums), formant synthesis.
5
+ *
6
+ * H(z) = ((1-R²)/2)·(1-z⁻²) / (1 - 2R*cos(w0)*z^-1 + R²*z^-2)
7
+ * where R = exp(-π*bw/fs), w0 = 2π*fc/fs
8
+ *
9
+ * cf. Julius O. Smith III, "Introduction to Digital Filters", Two-Pole
10
+ * section, "Constant Peak-Gain Resonator"
11
+ *
12
+ * @module audio-filter/effect/resonator
13
+ */
14
+
15
+ let {cos, exp, PI} = Math
16
+
17
+ export default function resonator (data, params) {
18
+ let fc = params.fc, fs = params.fs || 44100
19
+ if (fc == null) throw new Error('resonator: params.fc is required')
20
+ let bw = params.bw || 50
21
+
22
+ // Recompute coefficients if params changed (keys prefixed _r* — params may be a
23
+ // caller-owned object, eg speech/formant.js's per-band state, so must not collide
24
+ // with its own fields such as `gain`)
25
+ if (params._rFc !== fc || params._rBw !== bw || params._rFs !== fs) {
26
+ let R = exp(-PI * bw / fs)
27
+ let w0 = 2 * PI * fc / fs
28
+ params._rA1 = -2 * R * cos(w0)
29
+ params._rA2 = R * R
30
+ params._rB0 = (1 - R * R) / 2
31
+ params._rB2 = -params._rB0
32
+ params._rFc = fc
33
+ params._rBw = bw
34
+ params._rFs = fs
35
+ }
36
+
37
+ let a1 = params._rA1, a2 = params._rA2, b0 = params._rB0, b2 = params._rB2
38
+ let x1 = params._rX1 != null ? params._rX1 : 0
39
+ let x2 = params._rX2 != null ? params._rX2 : 0
40
+ let y1 = params._rY1 != null ? params._rY1 : 0
41
+ let y2 = params._rY2 != null ? params._rY2 : 0
42
+
43
+ for (let i = 0, l = data.length; i < l; i++) {
44
+ let x = data[i]
45
+ let y = b0 * x + b2 * x2 - a1 * y1 - a2 * y2
46
+ x2 = x1
47
+ x1 = x
48
+ y2 = y1
49
+ y1 = y
50
+ data[i] = y
51
+ }
52
+
53
+ params._rX1 = x1
54
+ params._rX2 = x2
55
+ params._rY1 = y1
56
+ params._rY2 = y2
57
+
58
+ return data
59
+ }