Skip to content

Commit 41bc625

Browse files
committed
2.4.1 — windows from window-function (scijs canon): fir/util.js fills over its per-sample evaluators, bit-identical (differential 0 across all 7), local formulas + besselI0 dropped; getWindow surface unchanged
1 parent d555675 commit 41bc625

3 files changed

Lines changed: 44 additions & 91 deletions

File tree

fir/util.js

Lines changed: 26 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,43 @@
1-
let { cos, sqrt, abs, PI } = Math
1+
// Windows come from window-function (scijs) — the canonical per-sample evaluators
2+
// (symmetric, N-1 denominator: scipy.signal.windows / Harris 1978 conventions).
3+
// This module only adapts them to FIR design's fill shape: name(N) → Float64Array.
4+
import {
5+
hamming as wfHamming, hann as wfHann, blackman as wfBlackman,
6+
blackmanHarris as wfBlackmanHarris, bartlett as wfBartlett,
7+
rectangular as wfRectangular, kaiser as wfKaiser,
8+
} from 'window-function'
29

3-
// Symmetric (sym=true) window definitions, N-1 denominator — matches
4-
// scipy.signal.windows / Harris 1978 "On the use of windows..." conventions.
5-
6-
/**
7-
* Hamming window.
8-
* @param {number} N - Window length
9-
* @returns {Float64Array}
10-
*/
11-
export function hamming (N) {
10+
const fill = (fn, N, ...args) => {
1211
let w = new Float64Array(N)
13-
for (let i = 0; i < N; i++) w[i] = 0.54 - 0.46 * cos(2 * PI * i / (N - 1))
12+
for (let i = 0; i < N; i++) w[i] = fn(i, N, ...args)
1413
return w
1514
}
1615

17-
/**
18-
* Hann window.
19-
* @param {number} N
20-
* @returns {Float64Array}
21-
*/
22-
export function hann (N) {
23-
let w = new Float64Array(N)
24-
for (let i = 0; i < N; i++) w[i] = 0.5 - 0.5 * cos(2 * PI * i / (N - 1))
25-
return w
26-
}
16+
/** Hamming window. @param {number} N @returns {Float64Array} */
17+
export const hamming = (N) => fill(wfHamming, N)
2718

28-
/**
29-
* Blackman window (a0=0.42, a1=0.5, a2=0.08).
30-
* @param {number} N
31-
* @returns {Float64Array}
32-
*/
33-
export function blackman (N) {
34-
let w = new Float64Array(N)
35-
for (let i = 0; i < N; i++) {
36-
let x = 2 * PI * i / (N - 1)
37-
w[i] = 0.42 - 0.5 * cos(x) + 0.08 * cos(2 * x)
38-
}
39-
return w
40-
}
19+
/** Hann window. @param {number} N @returns {Float64Array} */
20+
export const hann = (N) => fill(wfHann, N)
4121

42-
/**
43-
* 4-term Blackman-Harris window (-92 dB sidelobes).
44-
* @param {number} N
45-
* @returns {Float64Array}
46-
*/
47-
export function blackmanHarris (N) {
48-
let w = new Float64Array(N)
49-
for (let i = 0; i < N; i++) {
50-
let x = 2 * PI * i / (N - 1)
51-
w[i] = 0.35875 - 0.48829 * cos(x) + 0.14128 * cos(2 * x) - 0.01168 * cos(3 * x)
52-
}
53-
return w
54-
}
22+
/** Blackman window (a0=0.42, a1=0.5, a2=0.08). @param {number} N @returns {Float64Array} */
23+
export const blackman = (N) => fill(wfBlackman, N)
5524

56-
/**
57-
* Bartlett (triangular, zero-ended) window.
58-
* @param {number} N
59-
* @returns {Float64Array}
60-
*/
61-
export function bartlett (N) {
62-
let w = new Float64Array(N)
63-
for (let i = 0; i < N; i++) w[i] = 1 - abs(2 * i / (N - 1) - 1)
64-
return w
65-
}
25+
/** 4-term Blackman-Harris window (−92 dB sidelobes). @param {number} N @returns {Float64Array} */
26+
export const blackmanHarris = (N) => fill(wfBlackmanHarris, N)
6627

67-
/**
68-
* Rectangular (boxcar) window.
69-
* @param {number} N
70-
* @returns {Float64Array}
71-
*/
72-
export function rectangular (N) {
73-
return new Float64Array(N).fill(1)
74-
}
28+
/** Bartlett (triangular, zero-ended) window. @param {number} N @returns {Float64Array} */
29+
export const bartlett = (N) => fill(wfBartlett, N)
30+
31+
/** Rectangular (boxcar) window. @param {number} N @returns {Float64Array} */
32+
export const rectangular = (N) => fill(wfRectangular, N)
7533

7634
/**
77-
* Kaiser window: I0(beta*sqrt(1-x^2))/I0(beta), x = 2i/(N-1) - 1.
35+
* Kaiser window: I0(beta·sqrt(1−x²))/I0(beta), x = 2i/(N1) 1.
7836
* @param {number} N
79-
* @param {number} beta - Shape parameter (0 = rectangular; ~0.1102*(A-8.7) for A dB stopband)
37+
* @param {number} beta - Shape parameter (0 = rectangular; ~0.1102·(A−8.7) for A dB stopband)
8038
* @returns {Float64Array}
8139
*/
82-
export function kaiser (N, beta) {
83-
let w = new Float64Array(N)
84-
let denom = besselI0(beta)
85-
for (let i = 0; i < N; i++) {
86-
let x = 2 * i / (N - 1) - 1
87-
w[i] = besselI0(beta * sqrt(1 - x * x)) / denom
88-
}
89-
return w
90-
}
91-
92-
// Modified Bessel function of the first kind, order 0 (series expansion)
93-
function besselI0 (x) {
94-
let sum = 1, term = 1
95-
for (let k = 1; k < 50; k++) {
96-
term *= (x / (2 * k)) * (x / (2 * k))
97-
sum += term
98-
if (term < sum * 1e-16) break
99-
}
100-
return sum
101-
}
40+
export const kaiser = (N, beta) => fill(wfKaiser, N, beta)
10241

10342
const WINDOWS = {
10443
hamming, hann, hanning: hann, blackman,

package-lock.json

Lines changed: 14 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "digital-filter",
3-
"version": "2.4.0",
3+
"version": "2.4.1",
44
"type": "module",
55
"sideEffects": false,
66
"description": "Digital filter design & processing: IIR, FIR, smoothing, adaptive, multirate",
@@ -64,7 +64,9 @@
6464
"engines": {
6565
"node": ">=18"
6666
},
67-
"dependencies": {},
67+
"dependencies": {
68+
"window-function": "^3.0.1"
69+
},
6870
"devDependencies": {
6971
"tst": "^9.4.0"
7072
}

0 commit comments

Comments
 (0)