@audio/defeedback 1.0.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/LICENSE +40 -0
- package/README.md +15 -0
- package/index.js +44 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Kṛṣnized
|
|
2
|
+
|
|
3
|
+
This is a reminder that, in the absolute sense, all results of work belong to the Supreme.
|
|
4
|
+
|
|
5
|
+
While software and intellectual property (IP) require a formal license to define authorship,
|
|
6
|
+
responsibilities, or distribution limitations, these are temporary material designations.
|
|
7
|
+
The origin and destination of all ideas, as well as the ultimate owner of all results,
|
|
8
|
+
is the Supreme. The most meaningful action is to dedicate these results to the Supreme.
|
|
9
|
+
This process is known as Karma-Yoga and is described in BG 3.9, BG 12.10 and BG 18.46.
|
|
10
|
+
|
|
11
|
+
"Work done as a sacrifice for the Supreme must be performed;
|
|
12
|
+
otherwise, work binds one to the material world."
|
|
13
|
+
|
|
14
|
+
This license does not override or alter the terms specified by the material-level license below.
|
|
15
|
+
|
|
16
|
+
ॐ
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
MIT License
|
|
21
|
+
|
|
22
|
+
Copyright (c) Dmitry Iv
|
|
23
|
+
|
|
24
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
25
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
26
|
+
in the Software without restriction, including without limitation the rights
|
|
27
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
28
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
29
|
+
furnished to do so, subject to the following conditions:
|
|
30
|
+
|
|
31
|
+
The above copyright notice and this permission notice shall be included in all
|
|
32
|
+
copies or substantial portions of the Software.
|
|
33
|
+
|
|
34
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
35
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
36
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
37
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
38
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
39
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
40
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @audio/defeedback
|
|
2
|
+
|
|
3
|
+
> Adaptive feedback (howling) suppression — live-sound AFS class, **zero-latency direct path**.
|
|
4
|
+
|
|
5
|
+
| Package | What |
|
|
6
|
+
|---|---|
|
|
7
|
+
| `@audio/defeedback-analyzer` | spectral peaks + PNPR/PHPR howl criteria, parabolic freqs, relational harmonic gate (Waterschoot & Moonen 2011) |
|
|
8
|
+
| `@audio/defeedback-tracker` | persistence/stability/growth gating — the music discriminator |
|
|
9
|
+
| `@audio/defeedback-notchbank` | ≤12 pooled narrow IIR cuts, click-free coefficient morphing, deepen-on-redeploy |
|
|
10
|
+
|
|
11
|
+
The umbrella exports a streaming factory: `defeedback({fs, strength}) → {process(chunk), notches()}`. The audio path is pure IIR notches (0 samples latency); detection runs on the **post-notch** signal in parallel, so an insufficient notch deepens itself.
|
|
12
|
+
|
|
13
|
+
Verified by tests: a growing howl over music is suppressed ≥12 dB while the music stays ±1 dB; harmonic-rich tones deploy zero notches; and a **closed electro-acoustic loop simulation** (resonant room, loop gain > 1) runs away without the suppressor and stays bounded with it inline.
|
|
14
|
+
|
|
15
|
+
Design notes: detection must catch the howl pre-saturation (a clipped howl grows harmonics and reads as musical — same physics limits every AFS). Alpha Labs DeFeedback-class ML suppression (speech-trained model) is a different lane — see `@audio/neural`.
|
package/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// @audio/defeedback — adaptive feedback (howling) suppression, live-sound AFS class
|
|
2
|
+
// (dbx AFS / Sabine): ZERO-LATENCY direct path (pure IIR notch bank, no lookahead),
|
|
3
|
+
// detection runs on the post-notch signal in parallel — residual howl deepens its notch.
|
|
4
|
+
// Alpha Labs DeFeedback-style ML suppression is the @audio/neural lane; this is classical.
|
|
5
|
+
|
|
6
|
+
import analyze from '@audio/defeedback-analyzer'
|
|
7
|
+
import tracker from '@audio/defeedback-tracker'
|
|
8
|
+
import notchbank from '@audio/defeedback-notchbank'
|
|
9
|
+
|
|
10
|
+
export { analyze, tracker, notchbank }
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Streaming suppressor factory.
|
|
14
|
+
* @param {object} opts — { fs=44100, window=2048, hop=1024, maxNotches=12, q=30,
|
|
15
|
+
* strength=1 (0..1 scales notch depth), ...tracker/analyzer thresholds }
|
|
16
|
+
* @returns {{ process(chunk): chunk (in place, any block size), notches(): Array, reset() }}
|
|
17
|
+
*/
|
|
18
|
+
export default function defeedback ({ fs = 44100, window = 2048, hop = 1024, maxNotches = 12, q = 30, strength = 1, ...rest } = {}) {
|
|
19
|
+
let bank = notchbank({ fs, size: maxNotches, q, depth: -9 * strength, ...rest })
|
|
20
|
+
let trk = tracker(rest)
|
|
21
|
+
let ring = new Float32Array(window)
|
|
22
|
+
let fill = 0, sinceAnalysis = 0
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
process (chunk) {
|
|
26
|
+
bank.process(chunk) // zero-latency direct path
|
|
27
|
+
// sidechain: accumulate post-notch signal, analyze every `hop` samples
|
|
28
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
29
|
+
ring[fill % window] = chunk[i]
|
|
30
|
+
fill++
|
|
31
|
+
if (++sinceAnalysis >= hop && fill >= window) {
|
|
32
|
+
sinceAnalysis = 0
|
|
33
|
+
let frame = new Float32Array(window)
|
|
34
|
+
let start = fill % window
|
|
35
|
+
for (let j = 0; j < window; j++) frame[j] = ring[(start + j) % window]
|
|
36
|
+
for (let howl of trk.update(analyze(frame, { fs, ...rest }))) bank.deploy(howl.freq)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return chunk
|
|
40
|
+
},
|
|
41
|
+
notches: () => bank.notches(),
|
|
42
|
+
reset () { trk.reset() },
|
|
43
|
+
}
|
|
44
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio/defeedback",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"description": "Adaptive feedback suppression — umbrella for @audio/defeedback-* atoms (analyzer, tracker, notch bank)",
|
|
7
|
+
"workspaces": [
|
|
8
|
+
"packages/*"
|
|
9
|
+
],
|
|
10
|
+
"keywords": [
|
|
11
|
+
"audio",
|
|
12
|
+
"dsp",
|
|
13
|
+
"feedback",
|
|
14
|
+
"howling",
|
|
15
|
+
"notch",
|
|
16
|
+
"live-sound"
|
|
17
|
+
],
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "Dmitry Iv. <dfcreative@gmail.com>",
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=18"
|
|
22
|
+
},
|
|
23
|
+
"main": "index.js",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": "./index.js",
|
|
26
|
+
"./package.json": "./package.json"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"index.js"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"test": "node test.js",
|
|
33
|
+
"test:all": "npm test --workspaces --if-present && npm test",
|
|
34
|
+
"publish:all": "npm publish --workspaces && npm publish"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@audio/defeedback-analyzer": "^1.0.0",
|
|
38
|
+
"@audio/defeedback-tracker": "^1.0.0",
|
|
39
|
+
"@audio/defeedback-notchbank": "^1.0.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"tst": "^9.4.0"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
}
|
|
47
|
+
}
|