@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.
Files changed (2) hide show
  1. package/opto.js +40 -0
  2. 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
+ }