@audio/dynamics-varimu 0.1.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 +44 -0
- package/varimu.js +38 -0
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio/dynamics-varimu",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Vari-Mu compressor model — feedback detection, drive-dependent ratio, soft wide knee (Fairchild class)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "varimu.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./varimu.js",
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"varimu.js"
|
|
14
|
+
],
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@audio/dynamics-core": "^0.1.0",
|
|
17
|
+
"@audio/dynamics-envelope": "^0.1.0",
|
|
18
|
+
"@audio/dynamics-compressor": "^0.1.0"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"audio",
|
|
22
|
+
"dsp",
|
|
23
|
+
"dynamics",
|
|
24
|
+
"compressor",
|
|
25
|
+
"varimu"
|
|
26
|
+
],
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"author": "Dmitry Iv. <dfcreative@gmail.com>",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/audiojs/dynamics.git",
|
|
32
|
+
"directory": "packages/dynamics-varimu"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/audiojs/dynamics/tree/main/packages/dynamics-varimu",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/audiojs/dynamics/issues"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/varimu.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Vari-Mu compressor model (Fairchild class) — feedback topology (detector reads the
|
|
2
|
+
// output), very soft wide knee, slow attack, and ratio that grows with drive (the "mu").
|
|
3
|
+
import { envelope } from '@audio/dynamics-envelope'
|
|
4
|
+
import { compressorGain } from '@audio/dynamics-compressor'
|
|
5
|
+
import { writer, concat, db2lin, lin2db, timeCoef } from '@audio/dynamics-core'
|
|
6
|
+
|
|
7
|
+
export default function varimu (data, opts) {
|
|
8
|
+
if (!(data instanceof Float32Array)) return writer(varimuStream(data))
|
|
9
|
+
let s = varimuStream(opts)
|
|
10
|
+
return concat(s.write(data), s.flush())
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function varimuStream (opts = {}) {
|
|
14
|
+
let sr = opts.sampleRate || opts.fs || 44100
|
|
15
|
+
let threshold = opts.threshold ?? -22
|
|
16
|
+
let knee = opts.knee ?? 15
|
|
17
|
+
let makeup = opts.makeup ?? 0
|
|
18
|
+
let env = envelope({ ...opts, sampleRate: sr, detector: 'rms', attack: opts.attack ?? 25, release: 1 })
|
|
19
|
+
let gr = 0
|
|
20
|
+
let aCoef = timeCoef(opts.attack ?? 25, sr)
|
|
21
|
+
let rCoef = timeCoef(opts.release ?? 400, sr)
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
write (chunk) {
|
|
25
|
+
let out = new Float32Array(chunk.length)
|
|
26
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
27
|
+
let y = chunk[i] * db2lin(gr) // feedback: detect the compressed output
|
|
28
|
+
let over = lin2db(env(y)) - threshold
|
|
29
|
+
let mu = 1.8 + Math.max(0, over) / 5 // ratio grows with drive
|
|
30
|
+
let target = compressorGain(lin2db(env(y)) , threshold, mu, knee)
|
|
31
|
+
gr = target < gr ? target + (gr - target) * aCoef : target + (gr - target) * rCoef
|
|
32
|
+
out[i] = chunk[i] * db2lin(gr + makeup)
|
|
33
|
+
}
|
|
34
|
+
return out
|
|
35
|
+
},
|
|
36
|
+
flush () { return new Float32Array(0) }
|
|
37
|
+
}
|
|
38
|
+
}
|