@audio/filter-oberheim 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/oberheim.js +60 -0
  2. package/package.json +38 -0
package/oberheim.js ADDED
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Oberheim SEM state-variable filter (–12 dB/oct multimode).
3
+ * Zero-delay feedback (ZDF) via trapezoidal integration.
4
+ *
5
+ * Ref: Zavalishin, "The Art of VA Filter Design" (2012), Ch. 4–5.
6
+ *
7
+ * 2-pole SVF with continuous mode selection (lowpass, highpass, bandpass, notch).
8
+ * Two trapezoidal integrators with tanh saturation in the feedback path
9
+ * give the warm, musical character of the original SEM hardware.
10
+ *
11
+ * @module audio-filter/analog/oberheim
12
+ * @param {Float32Array|Float64Array} data - audio buffer (modified in place)
13
+ * @param {Object} params
14
+ * @param {number} [params.fc=1000] - cutoff frequency Hz
15
+ * @param {number} [params.resonance=0] - resonance 0–1 (max resonance at 1)
16
+ * @param {number} [params.fs=44100] - sample rate
17
+ * @param {string} [params.type='lowpass'] - 'lowpass'|'highpass'|'bandpass'|'notch'
18
+ */
19
+
20
+ let {tan, tanh, PI, min} = Math
21
+
22
+ export default function oberheim (data, params) {
23
+ let fc = params.fc || 1000
24
+ let res = params.resonance != null ? params.resonance : 0
25
+ let fs = params.fs || 44100
26
+ let type = params.type || 'lowpass'
27
+
28
+ // Trapezoidal integrator coefficient
29
+ let g = tan(PI * min(fc, fs * 0.49) / fs)
30
+ let R = 1 - res // damping: 1 = no resonance, 0 = max resonance
31
+
32
+ // State: 2 integrator states (bandpass, lowpass)
33
+ if (!params._s) params._s = new Float64Array(2)
34
+ let s = params._s
35
+
36
+ for (let i = 0, n = data.length; i < n; i++) {
37
+ // Implicit solve for highpass (ZDF: no unit delay in feedback)
38
+ let hp = (data[i] - 2 * R * s[0] - g * s[0] - s[1]) / (1 + 2 * R * g + g * g)
39
+
40
+ // Bandpass integrator (trapezoidal)
41
+ let bp = g * hp + s[0]
42
+ s[0] = g * hp + bp
43
+
44
+ // Lowpass integrator (trapezoidal)
45
+ let lp = g * bp + s[1]
46
+ s[1] = g * bp + lp
47
+
48
+ // Saturate feedback states (analog character)
49
+ s[0] = tanh(s[0])
50
+ s[1] = tanh(s[1])
51
+
52
+ // Mode select
53
+ data[i] = type === 'bandpass' ? bp
54
+ : type === 'highpass' ? hp
55
+ : type === 'notch' ? hp + lp
56
+ : lp
57
+ }
58
+
59
+ return data
60
+ }
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@audio/filter-oberheim",
3
+ "version": "1.0.0",
4
+ "description": "Oberheim SEM state-variable filter (–12 dB/oct multimode)",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "oberheim.js",
8
+ "exports": {
9
+ ".": "./oberheim.js",
10
+ "./package.json": "./package.json"
11
+ },
12
+ "files": [
13
+ "oberheim.js"
14
+ ],
15
+ "keywords": [
16
+ "audio",
17
+ "dsp",
18
+ "filter",
19
+ "oberheim"
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-oberheim"
27
+ },
28
+ "homepage": "https://github.com/audiojs/filter/tree/main/packages/filter-oberheim",
29
+ "bugs": {
30
+ "url": "https://github.com/audiojs/filter/issues"
31
+ },
32
+ "engines": {
33
+ "node": ">=18"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ }
38
+ }