@audio/dynamics-opto 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/opto.js +40 -0
- package/package.json +44 -0
package/opto.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Optical compressor model (LA-2A class) — RMS detection, wide soft knee, ~3:1, and the
|
|
2
|
+
// T4 signature: program-dependent release that slows the longer gain reduction persists.
|
|
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 opto (data, opts) {
|
|
8
|
+
if (!(data instanceof Float32Array)) return writer(optoStream(data))
|
|
9
|
+
let s = optoStream(opts)
|
|
10
|
+
return concat(s.write(data), s.flush())
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function optoStream (opts = {}) {
|
|
14
|
+
let sr = opts.sampleRate || opts.fs || 44100
|
|
15
|
+
let threshold = opts.threshold ?? -20
|
|
16
|
+
let ratio = opts.ratio ?? 3
|
|
17
|
+
let knee = opts.knee ?? 10
|
|
18
|
+
let makeup = opts.makeup ?? 0
|
|
19
|
+
let env = envelope({ ...opts, sampleRate: sr, detector: 'rms', attack: opts.attack ?? 10, release: 1 })
|
|
20
|
+
let gr = 0 // smoothed gain reduction (dB, ≤0)
|
|
21
|
+
let memory = 0 // integrates time-under-reduction → slows release (T4 cell)
|
|
22
|
+
let memCoef = timeCoef(3000, sr) // ~3 s history
|
|
23
|
+
let aCoef = timeCoef(opts.attack ?? 10, sr)
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
write (chunk) {
|
|
27
|
+
let out = new Float32Array(chunk.length)
|
|
28
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
29
|
+
let target = compressorGain(lin2db(env(chunk[i])), threshold, ratio, knee)
|
|
30
|
+
memory = memory * memCoef + (target < -1 ? 1 - memCoef : 0)
|
|
31
|
+
let relMs = (opts.release ?? 300) * (1 + 6 * memory)
|
|
32
|
+
let rCoef = timeCoef(relMs, sr)
|
|
33
|
+
gr = target < gr ? target + (gr - target) * aCoef : target + (gr - target) * rCoef
|
|
34
|
+
out[i] = chunk[i] * db2lin(gr + makeup)
|
|
35
|
+
}
|
|
36
|
+
return out
|
|
37
|
+
},
|
|
38
|
+
flush () { return new Float32Array(0) }
|
|
39
|
+
}
|
|
40
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio/dynamics-opto",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Optical compressor model — RMS detector, wide knee, T4 program-dependent release (LA-2A class)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "opto.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./opto.js",
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"opto.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
|
+
"opto"
|
|
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-opto"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/audiojs/dynamics/tree/main/packages/dynamics-opto",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/audiojs/dynamics/issues"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
}
|
|
44
|
+
}
|