@audio/effect-lofi 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/README.md +5 -0
- package/lofi.js +67 -0
- package/package.json +29 -0
package/README.md
ADDED
package/lofi.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lo-fi character (RC-20 class) — wow/flutter via LFO-modulated fractional delay,
|
|
3
|
+
* bandwidth ceiling/floor one-poles, tape saturation, vinyl noise bed + sparse crackle.
|
|
4
|
+
* Deterministic noise (seeded LCG) so renders are reproducible.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
let { sin, tanh, exp, PI } = Math
|
|
8
|
+
|
|
9
|
+
export default function lofi (data, params) {
|
|
10
|
+
let wow = params.wow ?? 0.3 // 0..1 — slow pitch drift (~0.7 Hz, up to 3 ms)
|
|
11
|
+
let flutter = params.flutter ?? 0.2 // 0..1 — fast wobble (~7 Hz, up to 0.4 ms)
|
|
12
|
+
let noise = params.noise ?? 0.1 // 0..1 — hiss bed level
|
|
13
|
+
let crackle = params.crackle ?? 0.1 // 0..1 — impulse density/level
|
|
14
|
+
let lowpass = params.lowpass ?? 6000 // bandwidth ceiling, Hz
|
|
15
|
+
let highpass = params.highpass ?? 60 // rumble floor, Hz
|
|
16
|
+
let drive = params.drive ?? 0.3 // 0..1 tape saturation
|
|
17
|
+
let fs = params.fs || 44100
|
|
18
|
+
|
|
19
|
+
let maxDelay = ((0.004 * fs) | 0) + 4
|
|
20
|
+
if (!params._buf) {
|
|
21
|
+
params._buf = new Float64Array(maxDelay * 2)
|
|
22
|
+
params._w = 0; params._ph1 = 0; params._ph2 = 0
|
|
23
|
+
params._lp1 = 0; params._lp2 = 0; params._lp3 = 0; params._hp = 0
|
|
24
|
+
params._rnd = params.seed ?? 0x2545f491
|
|
25
|
+
params._crk = 0
|
|
26
|
+
}
|
|
27
|
+
let buf = params._buf, N = buf.length, w = params._w
|
|
28
|
+
let ph1 = params._ph1, ph2 = params._ph2, hp = params._hp
|
|
29
|
+
let rnd = () => ((params._rnd = (params._rnd * 1664525 + 1013904223) >>> 0) / 4294967296)
|
|
30
|
+
|
|
31
|
+
let aLp = 1 - exp(-2 * PI * lowpass / fs)
|
|
32
|
+
let aHp = 1 - exp(-2 * PI * highpass / fs)
|
|
33
|
+
let g = 1 + drive * 4
|
|
34
|
+
let base = 0.004 * fs / 2 // center read offset
|
|
35
|
+
|
|
36
|
+
for (let i = 0, l = data.length; i < l; i++) {
|
|
37
|
+
buf[w] = data[i]
|
|
38
|
+
// modulated fractional-delay read: wow + flutter
|
|
39
|
+
let m = base + wow * 0.0015 * fs * sin(ph1) + flutter * 0.0002 * fs * sin(ph2)
|
|
40
|
+
ph1 += 2 * PI * 0.7 / fs; ph2 += 2 * PI * 7 / fs
|
|
41
|
+
let pos = w - m
|
|
42
|
+
let b0 = Math.floor(pos), frac = pos - b0
|
|
43
|
+
let s0 = buf[((b0 % N) + N) % N], s1 = buf[(((b0 + 1) % N) + N) % N]
|
|
44
|
+
let x = s0 + frac * (s1 - s0)
|
|
45
|
+
w = (w + 1) % N
|
|
46
|
+
|
|
47
|
+
// tape saturation, gain-compensated
|
|
48
|
+
if (drive > 0) x = tanh(x * g) / tanh(g)
|
|
49
|
+
|
|
50
|
+
// vinyl bed: hiss + crackle impulses with exponential tails
|
|
51
|
+
if (noise > 0) x += (rnd() - 0.5) * noise * 0.02
|
|
52
|
+
if (crackle > 0) {
|
|
53
|
+
if (rnd() < crackle * 0.0004) params._crk = (rnd() - 0.5) * crackle * 0.8
|
|
54
|
+
x += params._crk
|
|
55
|
+
params._crk *= 0.92
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// bandwidth: 3-pole LP ceiling (−18 dB/oct, tape-class), one-pole HP floor
|
|
59
|
+
params._lp1 += aLp * (x - params._lp1)
|
|
60
|
+
params._lp2 += aLp * (params._lp1 - params._lp2)
|
|
61
|
+
params._lp3 += aLp * (params._lp2 - params._lp3)
|
|
62
|
+
hp += aHp * (params._lp3 - hp)
|
|
63
|
+
data[i] = params._lp3 - hp
|
|
64
|
+
}
|
|
65
|
+
params._w = w; params._ph1 = ph1; params._ph2 = ph2; params._hp = hp
|
|
66
|
+
return data
|
|
67
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio/effect-lofi",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Lo-fi character — wow/flutter, vinyl noise, crackle, bandwidth ceiling (RC-20 class)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"keywords": [
|
|
8
|
+
"audio",
|
|
9
|
+
"dsp",
|
|
10
|
+
"effect",
|
|
11
|
+
"lofi"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "Dmitry Iv. <dfcreative@gmail.com>",
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18"
|
|
17
|
+
},
|
|
18
|
+
"main": "lofi.js",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": "./lofi.js",
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"lofi.js"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
}
|
|
29
|
+
}
|