@thi.ng/dsp 4.6.16 → 4.6.18
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/CHANGELOG.md +1 -1
- package/README.md +1 -1
- package/add.js +24 -38
- package/addg.js +4 -19
- package/adsr.js +148 -156
- package/agen.js +17 -21
- package/allpass.js +37 -38
- package/alt.js +26 -22
- package/anti-alias.js +8 -37
- package/api.js +0 -1
- package/aproc.js +24 -30
- package/biquad.js +188 -184
- package/bounce.js +15 -16
- package/complex.js +4 -1
- package/const.js +12 -13
- package/convert.js +18 -64
- package/cosine.js +43 -48
- package/curve.js +12 -41
- package/dcblock.js +9 -10
- package/delay.js +100 -111
- package/feedback-delay.js +23 -30
- package/fft.js +188 -334
- package/filter-delay.js +23 -27
- package/filter-response.js +22 -33
- package/foldback.js +26 -35
- package/impulse-train.js +35 -37
- package/impulse.js +27 -42
- package/integrator.js +27 -32
- package/internal/ensure.js +4 -1
- package/internal/take.js +8 -5
- package/iterable.js +32 -43
- package/line.js +10 -25
- package/madd.js +25 -40
- package/mapg.js +77 -69
- package/merge.js +18 -20
- package/mix.js +20 -16
- package/mul.js +24 -38
- package/multiplex.js +15 -11
- package/onepole.js +41 -42
- package/osc-additive.js +25 -53
- package/osc-cos.js +4 -1
- package/osc-dsf.js +15 -52
- package/osc-mix.js +6 -20
- package/osc-parabolic.js +4 -13
- package/osc-rect.js +6 -8
- package/osc-saw.js +4 -1
- package/osc-sin.js +4 -1
- package/osc-tri.js +4 -1
- package/osc-wavetable.js +12 -9
- package/osc.js +40 -74
- package/package.json +13 -10
- package/pan.js +23 -29
- package/pink-noise.js +35 -57
- package/pipe.js +6 -4
- package/power.js +40 -96
- package/product.js +5 -4
- package/reciprocal.js +20 -22
- package/ref.js +24 -20
- package/serial.js +59 -60
- package/sincos.js +45 -61
- package/sum.js +5 -4
- package/svf.js +74 -78
- package/sweep.js +4 -27
- package/waveshaper.js +41 -60
- package/white-noise.js +17 -23
- package/window.js +67 -52
package/cosine.js
CHANGED
|
@@ -1,51 +1,46 @@
|
|
|
1
1
|
import { TAU } from "@thi.ng/math/api";
|
|
2
2
|
import { AGen } from "./agen.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
setAmp(amp) {
|
|
43
|
-
this._amp = amp;
|
|
44
|
-
this.calcCoeffs();
|
|
45
|
-
}
|
|
46
|
-
calcCoeffs() {
|
|
47
|
-
this._nxt = this._amp;
|
|
48
|
-
this._cos = Math.cos(this._freq * TAU) * 2;
|
|
49
|
-
this._val = this._cos * this._amp * 0.5;
|
|
50
|
-
}
|
|
3
|
+
const cosine = (freq, amp) => new Cosine(freq, amp);
|
|
4
|
+
class Cosine extends AGen {
|
|
5
|
+
constructor(_freq, _amp = 1) {
|
|
6
|
+
super(0);
|
|
7
|
+
this._freq = _freq;
|
|
8
|
+
this._amp = _amp;
|
|
9
|
+
this.calcCoeffs();
|
|
10
|
+
}
|
|
11
|
+
_cos;
|
|
12
|
+
_nxt;
|
|
13
|
+
reset() {
|
|
14
|
+
this.calcCoeffs();
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
next() {
|
|
18
|
+
const t = this._nxt * this._cos - this._val;
|
|
19
|
+
this._val = this._nxt;
|
|
20
|
+
this._nxt = t;
|
|
21
|
+
return this._val;
|
|
22
|
+
}
|
|
23
|
+
freq() {
|
|
24
|
+
return this._freq;
|
|
25
|
+
}
|
|
26
|
+
setFreq(freq) {
|
|
27
|
+
this._freq = freq;
|
|
28
|
+
this.calcCoeffs();
|
|
29
|
+
}
|
|
30
|
+
amp() {
|
|
31
|
+
return this._amp;
|
|
32
|
+
}
|
|
33
|
+
setAmp(amp) {
|
|
34
|
+
this._amp = amp;
|
|
35
|
+
this.calcCoeffs();
|
|
36
|
+
}
|
|
37
|
+
calcCoeffs() {
|
|
38
|
+
this._nxt = this._amp;
|
|
39
|
+
this._cos = Math.cos(this._freq * TAU) * 2;
|
|
40
|
+
this._val = this._cos * this._amp * 0.5;
|
|
41
|
+
}
|
|
51
42
|
}
|
|
43
|
+
export {
|
|
44
|
+
Cosine,
|
|
45
|
+
cosine
|
|
46
|
+
};
|
package/curve.js
CHANGED
|
@@ -1,43 +1,14 @@
|
|
|
1
1
|
import { MAdd } from "./madd.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* Recommended range [0.0001 - 10000] (curved -> linear). Default: 0.1
|
|
15
|
-
*
|
|
16
|
-
* Also see {@link madd}.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```ts
|
|
20
|
-
* curve(-1, 1, 5, 0.1).take(7)
|
|
21
|
-
* // [
|
|
22
|
-
* // -1,
|
|
23
|
-
* // -0.04228753006664476,
|
|
24
|
-
* // 0.4786567612639258,
|
|
25
|
-
* // 0.7620225554764573,
|
|
26
|
-
* // 0.9161583712747458,
|
|
27
|
-
* // 1.0000000000000002, // target
|
|
28
|
-
* // 1.0456053557111122
|
|
29
|
-
* // ]
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* @param start - start value
|
|
33
|
-
* @param end - end value
|
|
34
|
-
* @param num - num steps
|
|
35
|
-
* @param rate - curvature control
|
|
36
|
-
* @param skipFirst - true to skip start value (default: false)
|
|
37
|
-
* @param clampEnd - true to clamp curve at end value (default: false)
|
|
38
|
-
*/
|
|
39
|
-
export const curve = (start, end, num, rate = 0.1, skipFirst = false, clampEnd = false) => {
|
|
40
|
-
const c = Math.exp(-Math.log((Math.abs(end - start) + rate) / rate) / num);
|
|
41
|
-
const offset = (start < end ? end + rate : end - rate) * (1 - c);
|
|
42
|
-
return new MAdd(c, skipFirst ? offset + start * c : start, offset, clampEnd ? end : undefined);
|
|
2
|
+
const curve = (start, end, num, rate = 0.1, skipFirst = false, clampEnd = false) => {
|
|
3
|
+
const c = Math.exp(-Math.log((Math.abs(end - start) + rate) / rate) / num);
|
|
4
|
+
const offset = (start < end ? end + rate : end - rate) * (1 - c);
|
|
5
|
+
return new MAdd(
|
|
6
|
+
c,
|
|
7
|
+
skipFirst ? offset + start * c : start,
|
|
8
|
+
offset,
|
|
9
|
+
clampEnd ? end : void 0
|
|
10
|
+
);
|
|
11
|
+
};
|
|
12
|
+
export {
|
|
13
|
+
curve
|
|
43
14
|
};
|
package/dcblock.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { OnePole } from "./onepole.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export const dcBlock = (freq) => new DCBlock("lp", freq);
|
|
8
|
-
export class DCBlock extends OnePole {
|
|
9
|
-
next(x) {
|
|
10
|
-
return x - super.next(x);
|
|
11
|
-
}
|
|
2
|
+
const dcBlock = (freq) => new DCBlock("lp", freq);
|
|
3
|
+
class DCBlock extends OnePole {
|
|
4
|
+
next(x) {
|
|
5
|
+
return x - super.next(x);
|
|
6
|
+
}
|
|
12
7
|
}
|
|
8
|
+
export {
|
|
9
|
+
DCBlock,
|
|
10
|
+
dcBlock
|
|
11
|
+
};
|
package/delay.js
CHANGED
|
@@ -2,117 +2,106 @@ import { isFunction } from "@thi.ng/checks/is-function";
|
|
|
2
2
|
import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
|
|
3
3
|
import { wrap } from "@thi.ng/math/interval";
|
|
4
4
|
import { AProc } from "./aproc.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
_rpos;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this._rpos = 0;
|
|
43
|
-
this._buf = new Array(n);
|
|
44
|
-
this.clear();
|
|
5
|
+
const delay = (n) => new Delay(n, 0);
|
|
6
|
+
const delayT = (n, off) => new Delay(n, off);
|
|
7
|
+
class Delay extends AProc {
|
|
8
|
+
/**
|
|
9
|
+
* Constructs new delay line of size `n` and initializes all
|
|
10
|
+
* elements to `empty`. If the latter is a function, the buffer will
|
|
11
|
+
* be initialized with the results of that function (called for each
|
|
12
|
+
* element).
|
|
13
|
+
*
|
|
14
|
+
* @param n -
|
|
15
|
+
* @param _empty -
|
|
16
|
+
*/
|
|
17
|
+
constructor(n, _empty) {
|
|
18
|
+
super(isFunction(_empty) ? _empty() : _empty);
|
|
19
|
+
this._empty = _empty;
|
|
20
|
+
if (n < 1)
|
|
21
|
+
illegalArgs("delay size must be >= 1");
|
|
22
|
+
n >>>= 0;
|
|
23
|
+
this._wpos = n - 1;
|
|
24
|
+
this._rpos = 0;
|
|
25
|
+
this._buf = new Array(n);
|
|
26
|
+
this.clear();
|
|
27
|
+
}
|
|
28
|
+
_buf;
|
|
29
|
+
_rpos;
|
|
30
|
+
_wpos;
|
|
31
|
+
get length() {
|
|
32
|
+
return this._buf.length;
|
|
33
|
+
}
|
|
34
|
+
clear() {
|
|
35
|
+
const { _buf, _empty } = this;
|
|
36
|
+
if (isFunction(_empty)) {
|
|
37
|
+
for (let i = _buf.length; i-- > 0; ) {
|
|
38
|
+
this._buf[i] = _empty();
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
this._buf.fill(_empty);
|
|
45
42
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
* @param t -
|
|
84
|
-
*/
|
|
85
|
-
tap(t) {
|
|
86
|
-
return this._buf[wrap((t | 0) + this._wpos, 0, this._buf.length - 1)];
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Takes an array of offsets relative to current write position,
|
|
90
|
-
* calls {@link Delay.tap} for each, writes results to `out` and
|
|
91
|
-
* returns it.
|
|
92
|
-
*/
|
|
93
|
-
multiTap(t, out = []) {
|
|
94
|
-
for (let i = t.length; i-- > 0;) {
|
|
95
|
-
out[i] = this.tap(t[i]);
|
|
96
|
-
}
|
|
97
|
-
return out;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Progresses read & write pos, stores new value and returns delayed value.
|
|
101
|
-
*
|
|
102
|
-
* @param x -
|
|
103
|
-
*/
|
|
104
|
-
next(x) {
|
|
105
|
-
this.step();
|
|
106
|
-
this._buf[this._wpos] = x;
|
|
107
|
-
return (this._val = this._buf[this._rpos]);
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Moves read & write cursors one step forward. Useful for skipping
|
|
111
|
-
* elements and/or to create gaps in the delay line.
|
|
112
|
-
*/
|
|
113
|
-
step() {
|
|
114
|
-
const n = this._buf.length;
|
|
115
|
-
++this._wpos >= n && (this._wpos -= n);
|
|
116
|
-
++this._rpos >= n && (this._rpos -= n);
|
|
43
|
+
}
|
|
44
|
+
copy() {
|
|
45
|
+
return new Delay(this._buf.length, this._empty);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Alias for {@link Delay.clear}
|
|
49
|
+
*/
|
|
50
|
+
reset() {
|
|
51
|
+
this.clear();
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Returns the delayed value at current read position (i.e. `n`
|
|
56
|
+
* samples behind current write pos, where `n` is the length of this
|
|
57
|
+
* delay line).
|
|
58
|
+
*/
|
|
59
|
+
deref() {
|
|
60
|
+
return this._buf[this._rpos];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Reads value at `t` relative to current write position. `t` should
|
|
64
|
+
* be in `(-∞..0)` interval. E.g. `tap(-1)` returns the second
|
|
65
|
+
* most recent value written.
|
|
66
|
+
*
|
|
67
|
+
* @param t -
|
|
68
|
+
*/
|
|
69
|
+
tap(t) {
|
|
70
|
+
return this._buf[wrap((t | 0) + this._wpos, 0, this._buf.length - 1)];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Takes an array of offsets relative to current write position,
|
|
74
|
+
* calls {@link Delay.tap} for each, writes results to `out` and
|
|
75
|
+
* returns it.
|
|
76
|
+
*/
|
|
77
|
+
multiTap(t, out = []) {
|
|
78
|
+
for (let i = t.length; i-- > 0; ) {
|
|
79
|
+
out[i] = this.tap(t[i]);
|
|
117
80
|
}
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Progresses read & write pos, stores new value and returns delayed value.
|
|
85
|
+
*
|
|
86
|
+
* @param x -
|
|
87
|
+
*/
|
|
88
|
+
next(x) {
|
|
89
|
+
this.step();
|
|
90
|
+
this._buf[this._wpos] = x;
|
|
91
|
+
return this._val = this._buf[this._rpos];
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Moves read & write cursors one step forward. Useful for skipping
|
|
95
|
+
* elements and/or to create gaps in the delay line.
|
|
96
|
+
*/
|
|
97
|
+
step() {
|
|
98
|
+
const n = this._buf.length;
|
|
99
|
+
++this._wpos >= n && (this._wpos -= n);
|
|
100
|
+
++this._rpos >= n && (this._rpos -= n);
|
|
101
|
+
}
|
|
118
102
|
}
|
|
103
|
+
export {
|
|
104
|
+
Delay,
|
|
105
|
+
delay,
|
|
106
|
+
delayT
|
|
107
|
+
};
|
package/feedback-delay.js
CHANGED
|
@@ -1,33 +1,26 @@
|
|
|
1
1
|
import { clamp01 } from "@thi.ng/math/interval";
|
|
2
2
|
import { Delay } from "./delay.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return new FeedbackDelay(this._buf.length, this._feedback);
|
|
23
|
-
}
|
|
24
|
-
next(x) {
|
|
25
|
-
return super.next(x + this._buf[this._rpos] * this._feedback);
|
|
26
|
-
}
|
|
27
|
-
feedback() {
|
|
28
|
-
return this._feedback;
|
|
29
|
-
}
|
|
30
|
-
setFeedback(feedback) {
|
|
31
|
-
this._feedback = clamp01(feedback);
|
|
32
|
-
}
|
|
3
|
+
const feedbackDelay = (n, feedback) => new FeedbackDelay(n, feedback);
|
|
4
|
+
class FeedbackDelay extends Delay {
|
|
5
|
+
constructor(n, _feedback = 0.5) {
|
|
6
|
+
super(n, 0);
|
|
7
|
+
this._feedback = _feedback;
|
|
8
|
+
this.setFeedback(_feedback);
|
|
9
|
+
}
|
|
10
|
+
copy() {
|
|
11
|
+
return new FeedbackDelay(this._buf.length, this._feedback);
|
|
12
|
+
}
|
|
13
|
+
next(x) {
|
|
14
|
+
return super.next(x + this._buf[this._rpos] * this._feedback);
|
|
15
|
+
}
|
|
16
|
+
feedback() {
|
|
17
|
+
return this._feedback;
|
|
18
|
+
}
|
|
19
|
+
setFeedback(feedback) {
|
|
20
|
+
this._feedback = clamp01(feedback);
|
|
21
|
+
}
|
|
33
22
|
}
|
|
23
|
+
export {
|
|
24
|
+
FeedbackDelay,
|
|
25
|
+
feedbackDelay
|
|
26
|
+
};
|