@audio/denoise-deesser 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/deesser.js +68 -0
- package/package.json +42 -0
package/deesser.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// De-esser — dynamic peaking EQ centred on the sibilance band.
|
|
2
|
+
//
|
|
3
|
+
// Detection runs on a HP-filtered side-chain (above `freq`); when the envelope
|
|
4
|
+
// exceeds threshold, a peaking EQ at `freq` with negative gain is engaged on
|
|
5
|
+
// the audio path. EQ gain follows the envelope continuously — recomputed every
|
|
6
|
+
// `block` samples for smoothness without per-sample coef cost.
|
|
7
|
+
//
|
|
8
|
+
// Standard for voice post-production. Unlike a static shelf, the cut only engages
|
|
9
|
+
// on loud 's' / 'sh' events, so dark consonants aren't thinned.
|
|
10
|
+
|
|
11
|
+
import { biquad, highpassCoefs, peakingCoefs, db2lin, lin2db } from '@audio/denoise-core'
|
|
12
|
+
|
|
13
|
+
export default function deesser(data, params = {}) {
|
|
14
|
+
let fs = params.fs || 44100
|
|
15
|
+
let freq = params.freq ?? 6000
|
|
16
|
+
let threshold = params.threshold ?? -30
|
|
17
|
+
let ratio = params.ratio ?? 4
|
|
18
|
+
let attack = params.attack ?? 0.001
|
|
19
|
+
let release = params.release ?? 0.05
|
|
20
|
+
let Q = params.Q ?? 1.4 // peaking EQ Q (narrower than 0.707)
|
|
21
|
+
let block = params.block ?? 64 // coef update interval
|
|
22
|
+
|
|
23
|
+
if (!params._init) {
|
|
24
|
+
params._init = true
|
|
25
|
+
params._scC = highpassCoefs(freq, 0.707, fs)
|
|
26
|
+
params._scS = [0, 0]
|
|
27
|
+
params._eqS = [0, 0]
|
|
28
|
+
params._env = 0
|
|
29
|
+
params._eqGainDb = 0
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let aA = Math.exp(-1 / (attack * fs))
|
|
33
|
+
let aR = Math.exp(-1 / (release * fs))
|
|
34
|
+
let aBlk = Math.exp(-block / (release * fs)) // EQ-gain smoothing across blocks
|
|
35
|
+
let thLin = db2lin(threshold)
|
|
36
|
+
|
|
37
|
+
// Sidechain: HP copy for detection
|
|
38
|
+
let sc = new Float32Array(data.length)
|
|
39
|
+
for (let i = 0; i < data.length; i++) sc[i] = data[i]
|
|
40
|
+
biquad(sc, params._scC.b0, params._scC.b1, params._scC.b2, params._scC.a1, params._scC.a2, params._scS)
|
|
41
|
+
|
|
42
|
+
let env = params._env
|
|
43
|
+
let eqDb = params._eqGainDb
|
|
44
|
+
|
|
45
|
+
for (let pos = 0; pos < data.length; pos += block) {
|
|
46
|
+
let end = Math.min(data.length, pos + block)
|
|
47
|
+
// update envelope across block, take peak
|
|
48
|
+
let peakEnv = env
|
|
49
|
+
for (let i = pos; i < end; i++) {
|
|
50
|
+
let x = Math.abs(sc[i])
|
|
51
|
+
env = x > env ? aA * env + (1 - aA) * x : aR * env + (1 - aR) * x
|
|
52
|
+
if (env > peakEnv) peakEnv = env
|
|
53
|
+
}
|
|
54
|
+
let target = 0
|
|
55
|
+
if (peakEnv > thLin) {
|
|
56
|
+
let over = lin2db(peakEnv / thLin)
|
|
57
|
+
target = -over * (1 - 1 / ratio) // negative dB cut
|
|
58
|
+
}
|
|
59
|
+
eqDb = target < eqDb ? aBlk * eqDb + (1 - aBlk) * target : aR * eqDb + (1 - aR) * target
|
|
60
|
+
|
|
61
|
+
let coef = peakingCoefs(freq, Q, eqDb, fs)
|
|
62
|
+
let blk = data.subarray(pos, end)
|
|
63
|
+
biquad(blk, coef.b0, coef.b1, coef.b2, coef.a1, coef.a2, params._eqS)
|
|
64
|
+
}
|
|
65
|
+
params._env = env
|
|
66
|
+
params._eqGainDb = eqDb
|
|
67
|
+
return data
|
|
68
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio/denoise-deesser",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "De-esser — dynamic peaking EQ centred on the sibilance band",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "deesser.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./deesser.js",
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"deesser.js"
|
|
14
|
+
],
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@audio/denoise-core": "^0.1.0"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"audio",
|
|
20
|
+
"dsp",
|
|
21
|
+
"denoise",
|
|
22
|
+
"restoration",
|
|
23
|
+
"deesser"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"author": "Dmitry Iv. <dfcreative@gmail.com>",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/audiojs/denoise.git",
|
|
30
|
+
"directory": "packages/denoise-deesser"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/audiojs/denoise/tree/main/packages/denoise-deesser",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/audiojs/denoise/issues"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
}
|
|
42
|
+
}
|