@audio/dynamics-vca 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/vca.js +36 -0
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio/dynamics-vca",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "VCA compressor model — clean feed-forward, near-hard knee (dbx/SSL bus class)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "vca.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./vca.js",
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"vca.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
|
+
"vca"
|
|
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-vca"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/audiojs/dynamics/tree/main/packages/dynamics-vca",
|
|
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/vca.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// VCA compressor model (dbx/SSL-bus class) — clean feed-forward peak detection,
|
|
2
|
+
// near-hard knee, precise dB-linear gain computation. The transparent workhorse.
|
|
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 vca (data, opts) {
|
|
8
|
+
if (!(data instanceof Float32Array)) return writer(vcaStream(data))
|
|
9
|
+
let s = vcaStream(opts)
|
|
10
|
+
return concat(s.write(data), s.flush())
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function vcaStream (opts = {}) {
|
|
14
|
+
let sr = opts.sampleRate || opts.fs || 44100
|
|
15
|
+
let threshold = opts.threshold ?? -20
|
|
16
|
+
let ratio = opts.ratio ?? 4
|
|
17
|
+
let knee = opts.knee ?? 1
|
|
18
|
+
let makeup = opts.makeup ?? 0
|
|
19
|
+
let env = envelope({ ...opts, sampleRate: sr, detector: 'peak', attack: opts.attack ?? 1, release: 1 })
|
|
20
|
+
let gr = 0
|
|
21
|
+
let aCoef = timeCoef(opts.attack ?? 1, sr)
|
|
22
|
+
let rCoef = timeCoef(opts.release ?? 150, sr)
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
write (chunk) {
|
|
26
|
+
let out = new Float32Array(chunk.length)
|
|
27
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
28
|
+
let target = compressorGain(lin2db(env(chunk[i])), threshold, ratio, knee)
|
|
29
|
+
gr = target < gr ? target + (gr - target) * aCoef : target + (gr - target) * rCoef
|
|
30
|
+
out[i] = chunk[i] * db2lin(gr + makeup)
|
|
31
|
+
}
|
|
32
|
+
return out
|
|
33
|
+
},
|
|
34
|
+
flush () { return new Float32Array(0) }
|
|
35
|
+
}
|
|
36
|
+
}
|