dsp-collection 0.2.5 → 0.2.7
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 +6 -2
- package/filter/FirFilterWin.d.ts +8 -0
- package/filter/FirFilterWin.d.ts.map +1 -0
- package/filter/FirFilterWin.js +55 -0
- package/filter/FirFilterWin.js.map +1 -0
- package/filter/SpecFilt.d.ts +11 -10
- package/filter/SpecFilt.d.ts.map +1 -0
- package/filter/SpecFilt.js +98 -98
- package/filter/SpecFilt.js.map +1 -1
- package/math/Complex.d.ts +43 -42
- package/math/Complex.d.ts.map +1 -0
- package/math/Complex.js +130 -129
- package/math/Complex.js.map +1 -1
- package/math/ComplexArray.d.ts +37 -36
- package/math/ComplexArray.d.ts.map +1 -0
- package/math/ComplexArray.js +170 -170
- package/math/ComplexArray.js.map +1 -1
- package/math/MathUtils.d.ts +10 -7
- package/math/MathUtils.d.ts.map +1 -0
- package/math/MathUtils.js +116 -81
- package/math/MathUtils.js.map +1 -1
- package/math/MutableComplex.d.ts +24 -22
- package/math/MutableComplex.d.ts.map +1 -0
- package/math/MutableComplex.js +68 -64
- package/math/MutableComplex.js.map +1 -1
- package/math/NumApprox.d.ts +4 -3
- package/math/NumApprox.d.ts.map +1 -0
- package/math/NumApprox.js +67 -67
- package/math/NumApprox.js.map +1 -1
- package/math/PolyReal.d.ts +14 -13
- package/math/PolyReal.d.ts.map +1 -0
- package/math/PolyReal.js +226 -226
- package/math/PolyReal.js.map +1 -1
- package/package.json +11 -3
- package/signal/AdaptiveStft.d.ts +13 -12
- package/signal/AdaptiveStft.d.ts.map +1 -0
- package/signal/AdaptiveStft.js +57 -57
- package/signal/AdaptiveStft.js.map +1 -1
- package/signal/Autocorrelation.d.ts +6 -5
- package/signal/Autocorrelation.d.ts.map +1 -0
- package/signal/Autocorrelation.js +53 -53
- package/signal/Autocorrelation.js.map +1 -1
- package/signal/Dft.d.ts +10 -9
- package/signal/Dft.d.ts.map +1 -0
- package/signal/Dft.js +87 -87
- package/signal/Dft.js.map +1 -1
- package/signal/EnvelopeDetection.d.ts +2 -1
- package/signal/EnvelopeDetection.d.ts.map +1 -0
- package/signal/EnvelopeDetection.js +9 -9
- package/signal/EnvelopeDetection.js.map +1 -1
- package/signal/Fft.d.ts +10 -9
- package/signal/Fft.d.ts.map +1 -0
- package/signal/Fft.js +275 -275
- package/signal/Fft.js.map +1 -1
- package/signal/Goertzel.d.ts +6 -5
- package/signal/Goertzel.d.ts.map +1 -0
- package/signal/Goertzel.js +48 -48
- package/signal/Goertzel.js.map +1 -1
- package/signal/InstFreq.d.ts +9 -8
- package/signal/InstFreq.d.ts.map +1 -0
- package/signal/InstFreq.js +26 -26
- package/signal/InstFreq.js.map +1 -1
- package/signal/PitchDetectionHarm.d.ts +27 -26
- package/signal/PitchDetectionHarm.d.ts.map +1 -0
- package/signal/PitchDetectionHarm.js +72 -68
- package/signal/PitchDetectionHarm.js.map +1 -1
- package/signal/Resampling.d.ts +8 -7
- package/signal/Resampling.d.ts.map +1 -0
- package/signal/Resampling.js +218 -218
- package/signal/Resampling.js.map +1 -1
- package/signal/WindowFunctions.d.ts +42 -40
- package/signal/WindowFunctions.d.ts.map +1 -0
- package/signal/WindowFunctions.js +194 -194
- package/signal/WindowFunctions.js.map +1 -1
- package/utils/ArrayUtils.d.ts +10 -9
- package/utils/ArrayUtils.d.ts.map +1 -0
- package/utils/ArrayUtils.js +68 -68
- package/utils/ArrayUtils.js.map +1 -1
- package/utils/DspUtils.d.ts +5 -2
- package/utils/DspUtils.d.ts.map +1 -0
- package/utils/DspUtils.js +12 -6
- package/utils/DspUtils.js.map +1 -1
- package/utils/MiscUtils.d.ts +7 -6
- package/utils/MiscUtils.d.ts.map +1 -0
- package/utils/MiscUtils.js +20 -20
- package/utils/MiscUtils.js.map +1 -1
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
# The
|
|
1
|
+
# The JavaScript DSP Collection
|
|
2
2
|
|
|
3
3
|
A collection of JavaScript modules for digital signal processing (written in TypeScript).
|
|
4
4
|
|
|
5
5
|
(This package is currently in development)
|
|
6
6
|
|
|
7
|
+
NPM package: [dsp-collection](https://www.npmjs.com/package/dsp-collection)
|
|
8
|
+
|
|
7
9
|
## Online test applications
|
|
8
10
|
|
|
9
11
|
* [Window functions test](https://www.source-code.biz/dsp/js/simpleTests/testWindowFunctions.html)
|
|
@@ -13,12 +15,14 @@ A collection of JavaScript modules for digital signal processing (written in Typ
|
|
|
13
15
|
|
|
14
16
|
* [HarmSyn - Harmonic synthesizer](https://www.source-code.biz/harmSyn)
|
|
15
17
|
* [KlattSyn - Klatt formant synthesizer](https://www.source-code.biz/klattSyn)
|
|
18
|
+
* [NoiseSyn - Spectral noise synthesizer](https://www.source-code.biz/noiseSyn)
|
|
16
19
|
* [SinSyn - Sinusoidal synthesizer](https://www.source-code.biz/sinSyn)
|
|
17
20
|
* [SpecFilt - Spectral filter tool](https://www.source-code.biz/specFilt)
|
|
18
21
|
|
|
19
22
|
## Associated JavaScript packages
|
|
20
23
|
|
|
21
|
-
* [commons-math-interpolation
|
|
24
|
+
* [commons-math-interpolation](https://github.com/chdh/commons-math-interpolation) - Interpolation and regression algorithms
|
|
22
25
|
* [Function curve editor widget](https://www.source-code.biz/snippets/typescript/functionCurveEditor)
|
|
23
26
|
* [Function curve viewer widget](https://www.source-code.biz/snippets/typescript/functionCurveViewer)
|
|
24
27
|
* [WAV file encoder](https://github.com/chdh/wav-file-encoder)
|
|
28
|
+
* [WAV file decoder](https://github.com/chdh/wav-file-decoder)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import MutableComplex from "../math/MutableComplex.ts";
|
|
2
|
+
import { WindowFunction } from "../signal/WindowFunctions.ts";
|
|
3
|
+
export declare function createWindowKernel(f: WindowFunction, width: number, symetric?: boolean): Float64Array;
|
|
4
|
+
export declare function createLpFilterKernel(windowFunctionId: string, normFirstMinFreq: number): Float64Array;
|
|
5
|
+
export declare function calcFreqRespAt(kernel: ArrayLike<number>, normFreq: number): MutableComplex;
|
|
6
|
+
export declare function applyFirKernelAt(signal: ArrayLike<number>, pos: number, kernel: ArrayLike<number>): number;
|
|
7
|
+
export declare function applyFirKernel(signal: ArrayLike<number>, kernel: Float64Array): Float64Array;
|
|
8
|
+
//# sourceMappingURL=FirFilterWin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FirFilterWin.d.ts","sourceRoot":"","sources":["../../src/filter/FirFilterWin.ts"],"names":[],"mappings":"AAEA,OAAO,cAAc,MAAM,2BAA2B,CAAC;AAEvD,OAAO,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAM5D,wBAAgB,kBAAkB,CAAE,CAAC,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,OAAc,GAAI,YAAY,CAK/F;AAKf,wBAAgB,oBAAoB,CAAE,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAI,YAAY,CAKzD;AAI/C,wBAAgB,cAAc,CAAE,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,CAEhD;AAY5C,wBAAgB,gBAAgB,CAAE,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,GAAI,MAAM,CAU7F;AAGhB,wBAAgB,cAAc,CAAE,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,GAAI,YAAY,CAI/E"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as WindowFunctions from "../signal/WindowFunctions.js";
|
|
2
|
+
import { goertzelSingle } from "../signal/Goertzel.js";
|
|
3
|
+
import * as ArrayUtils from "../utils/ArrayUtils.js";
|
|
4
|
+
export function createWindowKernel(f, width, symetric = true) {
|
|
5
|
+
const nudge = symetric ? 1 : 0;
|
|
6
|
+
const a1 = Float64Array.from({ length: width }, (_x, i) => f(i / (width - nudge)));
|
|
7
|
+
const sum = ArrayUtils.sum(a1);
|
|
8
|
+
const a2 = a1.map(x => x / sum);
|
|
9
|
+
return a2;
|
|
10
|
+
}
|
|
11
|
+
export function createLpFilterKernel(windowFunctionId, normFirstMinFreq) {
|
|
12
|
+
const descr = WindowFunctions.getFunctionDescrById(windowFunctionId);
|
|
13
|
+
const width = Math.round(descr.firstMinPos / normFirstMinFreq);
|
|
14
|
+
if (width < 3) {
|
|
15
|
+
throw new Error("Filter parameters out of range.");
|
|
16
|
+
}
|
|
17
|
+
return createWindowKernel(descr.f, width);
|
|
18
|
+
}
|
|
19
|
+
export function calcFreqRespAt(kernel, normFreq) {
|
|
20
|
+
const relFreq = normFreq * kernel.length;
|
|
21
|
+
return goertzelSingle(kernel, relFreq);
|
|
22
|
+
}
|
|
23
|
+
function reflectIndex(i, n) {
|
|
24
|
+
if (i >= 0 && i < n) {
|
|
25
|
+
return i;
|
|
26
|
+
}
|
|
27
|
+
if (n <= 1) {
|
|
28
|
+
return 0;
|
|
29
|
+
}
|
|
30
|
+
const period = 2 * (n - 1);
|
|
31
|
+
const t = (i % period + period) % period;
|
|
32
|
+
return (t < n) ? t : period - t;
|
|
33
|
+
}
|
|
34
|
+
export function applyFirKernelAt(signal, pos, kernel) {
|
|
35
|
+
if (pos < 0 || pos >= signal.length) {
|
|
36
|
+
return NaN;
|
|
37
|
+
}
|
|
38
|
+
const width = kernel.length;
|
|
39
|
+
const m = Math.floor(kernel.length / 2);
|
|
40
|
+
const p0 = pos - m;
|
|
41
|
+
let acc = 0;
|
|
42
|
+
for (let i = 0; i < width; i++) {
|
|
43
|
+
const p = reflectIndex(p0 + i, signal.length);
|
|
44
|
+
acc += signal[p] * kernel[i];
|
|
45
|
+
}
|
|
46
|
+
return acc;
|
|
47
|
+
}
|
|
48
|
+
export function applyFirKernel(signal, kernel) {
|
|
49
|
+
const out = new Float64Array(signal.length);
|
|
50
|
+
for (let i = 0; i < signal.length; i++) {
|
|
51
|
+
out[i] = applyFirKernelAt(signal, i, kernel);
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=FirFilterWin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FirFilterWin.js","sourceRoot":"","sources":["../../src/filter/FirFilterWin.ts"],"names":[],"mappings":"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"}
|
package/filter/SpecFilt.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export declare const enum FilterType {
|
|
2
|
-
lowPass = "LP",
|
|
3
|
-
highPass = "HP",
|
|
4
|
-
bandPass = "BP",
|
|
5
|
-
bandStop = "BS"
|
|
6
|
-
}
|
|
7
|
-
export
|
|
8
|
-
export declare function getFilterCurveFunction(filterType: FilterType, filterFreq1: number, filterFreq2: number, smoothingWidth: number): FilterCurveFunction;
|
|
9
|
-
export declare function applyFilterCurveFunction(inAmplitudes: ArrayLike<number>, scalingFactor: number, filterCurveFunction: FilterCurveFunction): Float64Array
|
|
10
|
-
export declare function filterSignal(inSamples: ArrayLike<number>, sampleRate: number, filterType: FilterType, filterFreq1: number, filterFreq2: number, smoothingWidth: number): Float64Array;
|
|
1
|
+
export declare const enum FilterType {
|
|
2
|
+
lowPass = "LP",
|
|
3
|
+
highPass = "HP",
|
|
4
|
+
bandPass = "BP",
|
|
5
|
+
bandStop = "BS"
|
|
6
|
+
}
|
|
7
|
+
export type FilterCurveFunction = (frequency: number) => number;
|
|
8
|
+
export declare function getFilterCurveFunction(filterType: FilterType, filterFreq1: number, filterFreq2: number, smoothingWidth: number): FilterCurveFunction;
|
|
9
|
+
export declare function applyFilterCurveFunction(inAmplitudes: ArrayLike<number>, scalingFactor: number, filterCurveFunction: FilterCurveFunction): Float64Array<ArrayBuffer>;
|
|
10
|
+
export declare function filterSignal(inSamples: ArrayLike<number>, sampleRate: number, filterType: FilterType, filterFreq1: number, filterFreq2: number, smoothingWidth: number): Float64Array;
|
|
11
|
+
//# sourceMappingURL=SpecFilt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpecFilt.d.ts","sourceRoot":"","sources":["../../src/filter/SpecFilt.ts"],"names":[],"mappings":"AASA,0BAAkB,UAAU;IACzB,OAAO,OAAQ;IACf,QAAQ,OAAO;IACf,QAAQ,OAAO;IACf,QAAQ,OAAO;CAAE;AAEpB,MAAM,MAAM,mBAAmB,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;AAoBhE,wBAAgB,sBAAsB,CAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAI,mBAAmB,CA2C9F;AAKzD,wBAAgB,wBAAwB,CAAE,YAAY,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,6BAOhH;AAwB1B,wBAAgB,YAAY,CAAE,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAI,YAAY,CAUlK"}
|
package/filter/SpecFilt.js
CHANGED
|
@@ -1,99 +1,99 @@
|
|
|
1
|
-
import ComplexArray from "../math/ComplexArray.js";
|
|
2
|
-
import * as Fft from "../signal/Fft.js";
|
|
3
|
-
function smoothingFunction(x) {
|
|
4
|
-
return (Math.sin(x * Math.PI / 2) + 1) / 2;
|
|
5
|
-
}
|
|
6
|
-
export function getFilterCurveFunction(filterType, filterFreq1, filterFreq2, smoothingWidth) {
|
|
7
|
-
switch (filterType) {
|
|
8
|
-
case "LP": {
|
|
9
|
-
return (freq) => {
|
|
10
|
-
if (freq < filterFreq1 - smoothingWidth) {
|
|
11
|
-
return 1;
|
|
12
|
-
}
|
|
13
|
-
else if (freq < filterFreq1 + smoothingWidth) {
|
|
14
|
-
return smoothingFunction((filterFreq1 - freq) / smoothingWidth);
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
return 0;
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
case "HP": {
|
|
22
|
-
return (freq) => {
|
|
23
|
-
if (freq < filterFreq1 - smoothingWidth) {
|
|
24
|
-
return 0;
|
|
25
|
-
}
|
|
26
|
-
else if (freq < filterFreq1 + smoothingWidth) {
|
|
27
|
-
return smoothingFunction((freq - filterFreq1) / smoothingWidth);
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
return 1;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
case "BP": {
|
|
35
|
-
return (freq) => {
|
|
36
|
-
if (freq < filterFreq1 - smoothingWidth) {
|
|
37
|
-
return 0;
|
|
38
|
-
}
|
|
39
|
-
else if (freq < filterFreq1 + smoothingWidth) {
|
|
40
|
-
return smoothingFunction((freq - filterFreq1) / smoothingWidth);
|
|
41
|
-
}
|
|
42
|
-
else if (freq < filterFreq2 - smoothingWidth) {
|
|
43
|
-
return 1;
|
|
44
|
-
}
|
|
45
|
-
else if (freq < filterFreq2 + smoothingWidth) {
|
|
46
|
-
return smoothingFunction((filterFreq2 - freq) / smoothingWidth);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
return 0;
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
case "BS": {
|
|
54
|
-
return (freq) => {
|
|
55
|
-
if (freq < filterFreq1 - smoothingWidth) {
|
|
56
|
-
return 1;
|
|
57
|
-
}
|
|
58
|
-
else if (freq < filterFreq1 + smoothingWidth) {
|
|
59
|
-
return smoothingFunction((filterFreq1 - freq) / smoothingWidth);
|
|
60
|
-
}
|
|
61
|
-
else if (freq < filterFreq2 - smoothingWidth) {
|
|
62
|
-
return 0;
|
|
63
|
-
}
|
|
64
|
-
else if (freq < filterFreq2 + smoothingWidth) {
|
|
65
|
-
return smoothingFunction((freq - filterFreq2) / smoothingWidth);
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
return 1;
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
default: {
|
|
73
|
-
throw new Error("Unsupported filter type.");
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
export function applyFilterCurveFunction(inAmplitudes, scalingFactor, filterCurveFunction) {
|
|
78
|
-
const n = inAmplitudes.length;
|
|
79
|
-
const outAmplitudes = new Float64Array(n);
|
|
80
|
-
for (let p = 0; p < n; p++) {
|
|
81
|
-
const frequency = p / scalingFactor;
|
|
82
|
-
const filterFactor = filterCurveFunction(frequency);
|
|
83
|
-
outAmplitudes[p] = filterFactor * inAmplitudes[p];
|
|
84
|
-
}
|
|
85
|
-
return outAmplitudes;
|
|
86
|
-
}
|
|
87
|
-
export function filterSignal(inSamples, sampleRate, filterType, filterFreq1, filterFreq2, smoothingWidth) {
|
|
88
|
-
const n = inSamples.length;
|
|
89
|
-
const inSpectrum = Fft.fftRealSpectrum(inSamples);
|
|
90
|
-
const inAmplitudes = inSpectrum.getAbsArray();
|
|
91
|
-
const inPhases = inSpectrum.getArgArray();
|
|
92
|
-
const filterCurveFunction = getFilterCurveFunction(filterType, filterFreq1, filterFreq2, smoothingWidth);
|
|
93
|
-
const outAmplitudes = applyFilterCurveFunction(inAmplitudes, n / sampleRate, filterCurveFunction);
|
|
94
|
-
const outPhases = inPhases;
|
|
95
|
-
const outSpectrum = ComplexArray.fromPolar(outAmplitudes, outPhases);
|
|
96
|
-
const outSignal = Fft.iFftRealHalf(outSpectrum, n);
|
|
97
|
-
return outSignal;
|
|
98
|
-
}
|
|
1
|
+
import ComplexArray from "../math/ComplexArray.js";
|
|
2
|
+
import * as Fft from "../signal/Fft.js";
|
|
3
|
+
function smoothingFunction(x) {
|
|
4
|
+
return (Math.sin(x * Math.PI / 2) + 1) / 2;
|
|
5
|
+
}
|
|
6
|
+
export function getFilterCurveFunction(filterType, filterFreq1, filterFreq2, smoothingWidth) {
|
|
7
|
+
switch (filterType) {
|
|
8
|
+
case "LP": {
|
|
9
|
+
return (freq) => {
|
|
10
|
+
if (freq < filterFreq1 - smoothingWidth) {
|
|
11
|
+
return 1;
|
|
12
|
+
}
|
|
13
|
+
else if (freq < filterFreq1 + smoothingWidth) {
|
|
14
|
+
return smoothingFunction((filterFreq1 - freq) / smoothingWidth);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return 0;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
case "HP": {
|
|
22
|
+
return (freq) => {
|
|
23
|
+
if (freq < filterFreq1 - smoothingWidth) {
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
else if (freq < filterFreq1 + smoothingWidth) {
|
|
27
|
+
return smoothingFunction((freq - filterFreq1) / smoothingWidth);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
return 1;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
case "BP": {
|
|
35
|
+
return (freq) => {
|
|
36
|
+
if (freq < filterFreq1 - smoothingWidth) {
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
else if (freq < filterFreq1 + smoothingWidth) {
|
|
40
|
+
return smoothingFunction((freq - filterFreq1) / smoothingWidth);
|
|
41
|
+
}
|
|
42
|
+
else if (freq < filterFreq2 - smoothingWidth) {
|
|
43
|
+
return 1;
|
|
44
|
+
}
|
|
45
|
+
else if (freq < filterFreq2 + smoothingWidth) {
|
|
46
|
+
return smoothingFunction((filterFreq2 - freq) / smoothingWidth);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
case "BS": {
|
|
54
|
+
return (freq) => {
|
|
55
|
+
if (freq < filterFreq1 - smoothingWidth) {
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
else if (freq < filterFreq1 + smoothingWidth) {
|
|
59
|
+
return smoothingFunction((filterFreq1 - freq) / smoothingWidth);
|
|
60
|
+
}
|
|
61
|
+
else if (freq < filterFreq2 - smoothingWidth) {
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
else if (freq < filterFreq2 + smoothingWidth) {
|
|
65
|
+
return smoothingFunction((freq - filterFreq2) / smoothingWidth);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
return 1;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
default: {
|
|
73
|
+
throw new Error("Unsupported filter type.");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export function applyFilterCurveFunction(inAmplitudes, scalingFactor, filterCurveFunction) {
|
|
78
|
+
const n = inAmplitudes.length;
|
|
79
|
+
const outAmplitudes = new Float64Array(n);
|
|
80
|
+
for (let p = 0; p < n; p++) {
|
|
81
|
+
const frequency = p / scalingFactor;
|
|
82
|
+
const filterFactor = filterCurveFunction(frequency);
|
|
83
|
+
outAmplitudes[p] = filterFactor * inAmplitudes[p];
|
|
84
|
+
}
|
|
85
|
+
return outAmplitudes;
|
|
86
|
+
}
|
|
87
|
+
export function filterSignal(inSamples, sampleRate, filterType, filterFreq1, filterFreq2, smoothingWidth) {
|
|
88
|
+
const n = inSamples.length;
|
|
89
|
+
const inSpectrum = Fft.fftRealSpectrum(inSamples);
|
|
90
|
+
const inAmplitudes = inSpectrum.getAbsArray();
|
|
91
|
+
const inPhases = inSpectrum.getArgArray();
|
|
92
|
+
const filterCurveFunction = getFilterCurveFunction(filterType, filterFreq1, filterFreq2, smoothingWidth);
|
|
93
|
+
const outAmplitudes = applyFilterCurveFunction(inAmplitudes, n / sampleRate, filterCurveFunction);
|
|
94
|
+
const outPhases = inPhases;
|
|
95
|
+
const outSpectrum = ComplexArray.fromPolar(outAmplitudes, outPhases);
|
|
96
|
+
const outSignal = Fft.iFftRealHalf(outSpectrum, n);
|
|
97
|
+
return outSignal;
|
|
98
|
+
}
|
|
99
99
|
//# sourceMappingURL=SpecFilt.js.map
|
package/filter/SpecFilt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpecFilt.js","sourceRoot":"","sources":["../../src/filter/SpecFilt.ts"],"names":[],"mappings":"AAMA,OAAO,YAAY,MAAM,yBAAyB,CAAC;AACnD,OAAO,KAAK,GAAG,MAAM,kBAAkB,CAAC;AAWxC,SAAS,iBAAiB,CAAE,CAAS;IAClC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;AAAC,CAAC;AAgBhD,MAAM,UAAU,sBAAsB,CAAE,UAAsB,EAAE,WAAmB,EAAE,WAAmB,EAAE,cAAsB;IAC7H,QAAQ,UAAU,EAAE;
|
|
1
|
+
{"version":3,"file":"SpecFilt.js","sourceRoot":"","sources":["../../src/filter/SpecFilt.ts"],"names":[],"mappings":"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"}
|
package/math/Complex.d.ts
CHANGED
|
@@ -1,42 +1,43 @@
|
|
|
1
|
-
export default class Complex {
|
|
2
|
-
static readonly I: Complex;
|
|
3
|
-
static readonly ZERO: Complex;
|
|
4
|
-
static readonly ONE: Complex;
|
|
5
|
-
static readonly TWO: Complex;
|
|
6
|
-
static readonly NaN: Complex;
|
|
7
|
-
static readonly INFINITY: Complex;
|
|
8
|
-
readonly re: number;
|
|
9
|
-
readonly im: number;
|
|
10
|
-
constructor(re: number, im?: number);
|
|
11
|
-
toString(): string;
|
|
12
|
-
toNumber(eps: number): number;
|
|
13
|
-
isNaN(): boolean;
|
|
14
|
-
isInfinite(): boolean;
|
|
15
|
-
isFinite(): boolean;
|
|
16
|
-
equals(x: Complex): boolean;
|
|
17
|
-
fuzzyEquals(x: Complex, eps: number): boolean;
|
|
18
|
-
static expj(arg: number): Complex;
|
|
19
|
-
static fromPolar(abs: number, arg: number): Complex;
|
|
20
|
-
abs(): number;
|
|
21
|
-
arg(): number;
|
|
22
|
-
conj(): Complex;
|
|
23
|
-
neg(): Complex;
|
|
24
|
-
reciprocal(): Complex;
|
|
25
|
-
exp(): Complex;
|
|
26
|
-
log(): Complex;
|
|
27
|
-
sqr(): Complex;
|
|
28
|
-
sqrt(): Complex;
|
|
29
|
-
addReal(x: number): Complex;
|
|
30
|
-
add(x: Complex): Complex;
|
|
31
|
-
subReal(x: number): Complex;
|
|
32
|
-
static subFromReal(x: number, y: Complex): Complex;
|
|
33
|
-
sub(x: Complex): Complex;
|
|
34
|
-
mulReal(x: number): Complex;
|
|
35
|
-
mul(x: Complex): Complex;
|
|
36
|
-
divReal(x: number): Complex;
|
|
37
|
-
div(x: Complex): Complex;
|
|
38
|
-
static divFromReal(x: number, y: Complex): Complex;
|
|
39
|
-
powInt(x: number): Complex;
|
|
40
|
-
powReal(x: number): Complex;
|
|
41
|
-
pow(x: Complex): Complex;
|
|
42
|
-
}
|
|
1
|
+
export default class Complex {
|
|
2
|
+
static readonly I: Complex;
|
|
3
|
+
static readonly ZERO: Complex;
|
|
4
|
+
static readonly ONE: Complex;
|
|
5
|
+
static readonly TWO: Complex;
|
|
6
|
+
static readonly NaN: Complex;
|
|
7
|
+
static readonly INFINITY: Complex;
|
|
8
|
+
readonly re: number;
|
|
9
|
+
readonly im: number;
|
|
10
|
+
constructor(re: number, im?: number);
|
|
11
|
+
toString(): string;
|
|
12
|
+
toNumber(eps: number): number;
|
|
13
|
+
isNaN(): boolean;
|
|
14
|
+
isInfinite(): boolean;
|
|
15
|
+
isFinite(): boolean;
|
|
16
|
+
equals(x: Complex): boolean;
|
|
17
|
+
fuzzyEquals(x: Complex, eps: number): boolean;
|
|
18
|
+
static expj(arg: number): Complex;
|
|
19
|
+
static fromPolar(abs: number, arg: number): Complex;
|
|
20
|
+
abs(): number;
|
|
21
|
+
arg(): number;
|
|
22
|
+
conj(): Complex;
|
|
23
|
+
neg(): Complex;
|
|
24
|
+
reciprocal(): Complex;
|
|
25
|
+
exp(): Complex;
|
|
26
|
+
log(): Complex;
|
|
27
|
+
sqr(): Complex;
|
|
28
|
+
sqrt(): Complex;
|
|
29
|
+
addReal(x: number): Complex;
|
|
30
|
+
add(x: Complex): Complex;
|
|
31
|
+
subReal(x: number): Complex;
|
|
32
|
+
static subFromReal(x: number, y: Complex): Complex;
|
|
33
|
+
sub(x: Complex): Complex;
|
|
34
|
+
mulReal(x: number): Complex;
|
|
35
|
+
mul(x: Complex): Complex;
|
|
36
|
+
divReal(x: number): Complex;
|
|
37
|
+
div(x: Complex): Complex;
|
|
38
|
+
static divFromReal(x: number, y: Complex): Complex;
|
|
39
|
+
powInt(x: number): Complex;
|
|
40
|
+
powReal(x: number): Complex;
|
|
41
|
+
pow(x: Complex): Complex;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=Complex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Complex.d.ts","sourceRoot":"","sources":["../../src/math/Complex.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,OAAO,OAAO,OAAO;IAOzB,gBAAuB,CAAC,UAAqB;IAG7C,gBAAuB,IAAI,UAAkB;IAG7C,gBAAuB,GAAG,UAAkB;IAG5C,gBAAuB,GAAG,UAAkB;IAG5C,gBAAuB,GAAG,UAAyB;IAGnD,gBAAuB,QAAQ,UAAmC;IAOlE,SAAgB,EAAE,EAAE,MAAM,CAAC;IAG3B,SAAgB,EAAE,EAAE,MAAM,CAAC;gBAYP,EAAE,EAAE,MAAM,EAAE,EAAE,GAAE,MAAU;IASvC,QAAQ,IAAK,MAAM;IAOnB,QAAQ,CAAE,GAAG,EAAE,MAAM,GAAI,MAAM;IAS/B,KAAK,IAAK,OAAO;IAMjB,UAAU;IAMV,QAAQ;IAMR,MAAM,CAAE,CAAC,EAAE,OAAO,GAAI,OAAO;IAO7B,WAAW,CAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAI,OAAO;WAQxC,IAAI,CAAE,GAAG,EAAE,MAAM,GAAI,OAAO;WAM5B,SAAS,CAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAI,OAAO;IAQrD,GAAG,IAAK,MAAM;IAMd,GAAG,IAAK,MAAM;IAMd,IAAI,IAAK,OAAO;IAMhB,GAAG,IAAK,OAAO;IAMf,UAAU,IAAK,OAAO;IActB,GAAG,IAAK,OAAO;IAMf,GAAG,IAAK,OAAO;IAMf,GAAG,IAAK,OAAO;IAMf,IAAI,IAAK,OAAO;IAWhB,OAAO,CAAE,CAAC,EAAE,MAAM,GAAI,OAAO;IAM7B,GAAG,CAAE,CAAC,EAAE,OAAO,GAAI,OAAO;IAM1B,OAAO,CAAE,CAAC,EAAE,MAAM,GAAI,OAAO;WAMtB,WAAW,CAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,GAAI,OAAO;IAMpD,GAAG,CAAE,CAAC,EAAE,OAAO,GAAI,OAAO;IAM1B,OAAO,CAAE,CAAC,EAAE,MAAM,GAAI,OAAO;IAM7B,GAAG,CAAE,CAAC,EAAE,OAAO,GAAI,OAAO;IAM1B,OAAO,CAAE,CAAC,EAAE,MAAM,GAAI,OAAO;IAM7B,GAAG,CAAE,CAAC,EAAE,OAAO,GAAI,OAAO;WAOnB,WAAW,CAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,GAAI,OAAO;IAOpD,MAAM,CAAE,CAAC,EAAE,MAAM,GAAI,OAAO;IAQ5B,OAAO,CAAE,CAAC,EAAE,MAAM,GAAI,OAAO;IAM7B,GAAG,CAAE,CAAC,EAAE,OAAO,GAAI,OAAO;CAGhC"}
|