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