FA-91501 / Digital signal filters / Open access
Windowed sinc ignores the cutoff in the sinc argument · case 01
All cutoffs yield the same (full-band) impulse shape.
ROOT CAUSE
The sinc is evaluated at t instead of fc t.
VERIFIED REPAIR
Use sin(pi fc t)/(pi fc t).
Unsuccessful approach: The attempted repair halves the argument (fc t / 2), confusing Nyquist-relative and sample-rate-relative cutoffs.
Case contract
Input [N, fc, window]; fc is the cutoff as a fraction of Nyquist in (0, 1], window hamming (0.54 - 0.46 cos(2 pi n/(N-1))), hann (0.5 - 0.5 cos(...)) or rect (N = 1 uses 1). Taps h[n] = fc sinc(fc (n - (N-1)/2)) w[n], normalized to unit DC gain and rounded to 8 decimals; "bad-spec" for invalid input (Hann needs N != 2).
Why this case matters
Windowed-sinc design is the default FIR recipe; centre or normalization slips yield non-linear-phase or wrong-gain filters.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
N, fc_s, win = x
fc = float(Fraction(fc_s))
if N < 1 or not 0 < fc <= 1:
return 'bad-spec'
c = (N - 1) / 2
taps = []
for n in range(N):
t = n - c
s = 1.0 if t == 0 else math.sin(math.pi * t) / (math.pi * t)
if N == 1 or win == 'rect':
w = 1.0
elif win == 'hann':
w = 0.5 - 0.5 * math.cos(2 * math.pi * n / (N - 1))
else:
w = 0.54 - 0.46 * math.cos(2 * math.pi * n / (N - 1))
taps.append(fc * s * w)
tot = sum(taps)
return [round(v / tot, 8) + 0.0 for v in taps]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: N=4 fc=1/2 hamming', [4, '1/2', 'hamming'], [0.0167364, 0.4832636, 0.4832636, 0.0167364]], ['regression: N=4 fc=1/2 rect', [4, '1/2', 'rect'], [0.125, 0.375, 0.375, 0.125]], ['regression: N=4 fc=1/4 hamming', [4, '1/4', 'hamming'], [0.03857901, 0.46142099, 0.46142099, 0.03857901]], ['control: N=1 fc=1/2 hamming', [1, '1/2', 'hamming'], [1.0]], ['control: N=1 fc=1/2 hann', [1, '1/2', 'hann'], [1.0]], ['control: N=1 fc=1/2 rect', [1, '1/2', 'rect'], [1.0]], ['control: N=1 fc=1/4 hamming', [1, '1/4', 'hamming'], [1.0]]], [['regression: N=4 fc=1/4 rect', [4, '1/4', 'rect'], [0.22295145, 0.27704855, 0.27704855, 0.22295145]], ['regression: N=4 fc=3/5 hamming', [4, '3/5', 'hamming'], [0.00652778, 0.49347222, 0.49347222, 0.00652778]], ['regression: N=4 fc=1/4 hamming', [4, '1/4', 'hamming'], [0.03857901, 0.46142099, 0.46142099, 0.03857901]], ['control: N=1 fc=1/4 hann', [1, '1/4', 'hann'], [1.0]], ['control: N=1 fc=1/4 rect', [1, '1/4', 'rect'], [1.0]], ['control: N=1 fc=3/5 hamming', [1, '3/5', 'hamming'], [1.0]], ['control: N=1 fc=3/5 hann', [1, '3/5', 'hann'], [1.0]]], [['regression: N=5 fc=1/2 hamming', [5, '1/2', 'hamming'], [0.0, 0.20371237, 0.59257526, 0.20371237, 0.0]], ['regression: N=5 fc=1/2 hann', [5, '1/2', 'hann'], [0.0, 0.19449226, 0.61101547, 0.19449226, 0.0]], ['regression: N=4 fc=3/5 hamming', [4, '3/5', 'hamming'], [0.00652778, 0.49347222, 0.49347222, 0.00652778]], ['control: N=1 fc=3/5 rect', [1, '3/5', 'rect'], [1.0]], ['control: N=1 fc=1 hamming', [1, '1', 'hamming'], [1.0]], ['control: N=1 fc=1 hann', [1, '1', 'hann'], [1.0]], ['control: N=1 fc=1 rect', [1, '1', 'rect'], [1.0]]], [['regression: N=5 fc=1/4 hamming', [5, '1/4', 'hamming'], [0.02455383, 0.23438946, 0.4821134, 0.23438946, 0.02455383]], ['regression: N=5 fc=1/4 hann', [5, '1/4', 'hann'], [0.0, 0.23688591, 0.52622818, 0.23688591, 0.0]], ['repair check: N=4 fc=1 hamming', [4, '1', 'hamming'], [-0.01793722, 0.51793722, 0.51793722, -0.01793722]], ['control: N=2 fc=1/2 hamming', [2, '1/2', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=1/2 rect', [2, '1/2', 'rect'], [0.5, 0.5]], ['control: N=2 fc=1/4 hamming', [2, '1/4', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=1/4 rect', [2, '1/4', 'rect'], [0.5, 0.5]]], [['regression: N=5 fc=3/5 hamming', [5, '3/5', 'hamming'], [-0.00820621, 0.17925211, 0.65790821, 0.17925211, -0.00820621]], ['regression: N=5 fc=3/5 hann', [5, '3/5', 'hann'], [0.0, 0.16767497, 0.66465005, 0.16767497, 0.0]], ['regression: N=5 fc=1/2 hamming', [5, '1/2', 'hamming'], [0.0, 0.20371237, 0.59257526, 0.20371237, 0.0]], ['control: N=2 fc=3/5 hamming', [2, '3/5', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=3/5 rect', [2, '3/5', 'rect'], [0.5, 0.5]], ['control: N=2 fc=1 hamming', [2, '1', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=1 rect', [2, '1', 'rect'], [0.5, 0.5]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: N=4 fc=1/2 hamming | [-0.01793722, 0.51793722, 0.51793722, -0.01793722] | [0.0167364, 0.4832636, 0.4832636, 0.0167364] | Failed |
| regression: N=4 fc=1/2 rect | [-0.25, 0.75, 0.75, -0.25] | [0.125, 0.375, 0.375, 0.125] | Failed |
| regression: N=4 fc=1/4 hamming | [-0.01793722, 0.51793722, 0.51793722, -0.01793722] | [0.03857901, 0.46142099, 0.46142099, 0.03857901] | Failed |
| control: N=1 fc=1/2 hamming | [1.0] | [1.0] | Passed |
| control: N=1 fc=1/2 hann | [1.0] | [1.0] | Passed |
| control: N=1 fc=1/2 rect | [1.0] | [1.0] | Passed |
| control: N=1 fc=1/4 hamming | [1.0] | [1.0] | Passed |
SHA-256 / 8af77cc6c98428fc077a968cebdb6e1efa0f6761e2ccfc67576f14a169c4e82e
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
N, fc_s, win = x
fc = float(Fraction(fc_s))
if N < 1 or not 0 < fc <= 1:
return 'bad-spec'
c = (N - 1) / 2
taps = []
for n in range(N):
t = n - c
s = 1.0 if t == 0 else math.sin(math.pi * fc * t / 2) / (math.pi * fc * t / 2)
if N == 1 or win == 'rect':
w = 1.0
elif win == 'hann':
w = 0.5 - 0.5 * math.cos(2 * math.pi * n / (N - 1))
else:
w = 0.54 - 0.46 * math.cos(2 * math.pi * n / (N - 1))
taps.append(fc * s * w)
tot = sum(taps)
return [round(v / tot, 8) + 0.0 for v in taps]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: N=4 fc=1/2 hamming', [4, '1/2', 'hamming'], [0.0167364, 0.4832636, 0.4832636, 0.0167364]], ['regression: N=4 fc=1/2 rect', [4, '1/2', 'rect'], [0.125, 0.375, 0.375, 0.125]], ['regression: N=4 fc=1/4 hamming', [4, '1/4', 'hamming'], [0.03857901, 0.46142099, 0.46142099, 0.03857901]], ['control: N=1 fc=1/2 hamming', [1, '1/2', 'hamming'], [1.0]], ['control: N=1 fc=1/2 hann', [1, '1/2', 'hann'], [1.0]], ['control: N=1 fc=1/2 rect', [1, '1/2', 'rect'], [1.0]], ['control: N=1 fc=1/4 hamming', [1, '1/4', 'hamming'], [1.0]]], [['regression: N=4 fc=1/4 rect', [4, '1/4', 'rect'], [0.22295145, 0.27704855, 0.27704855, 0.22295145]], ['regression: N=4 fc=3/5 hamming', [4, '3/5', 'hamming'], [0.00652778, 0.49347222, 0.49347222, 0.00652778]], ['regression: N=4 fc=1/4 hamming', [4, '1/4', 'hamming'], [0.03857901, 0.46142099, 0.46142099, 0.03857901]], ['control: N=1 fc=1/4 hann', [1, '1/4', 'hann'], [1.0]], ['control: N=1 fc=1/4 rect', [1, '1/4', 'rect'], [1.0]], ['control: N=1 fc=3/5 hamming', [1, '3/5', 'hamming'], [1.0]], ['control: N=1 fc=3/5 hann', [1, '3/5', 'hann'], [1.0]]], [['regression: N=5 fc=1/2 hamming', [5, '1/2', 'hamming'], [0.0, 0.20371237, 0.59257526, 0.20371237, 0.0]], ['regression: N=5 fc=1/2 hann', [5, '1/2', 'hann'], [0.0, 0.19449226, 0.61101547, 0.19449226, 0.0]], ['regression: N=4 fc=3/5 hamming', [4, '3/5', 'hamming'], [0.00652778, 0.49347222, 0.49347222, 0.00652778]], ['control: N=1 fc=3/5 rect', [1, '3/5', 'rect'], [1.0]], ['control: N=1 fc=1 hamming', [1, '1', 'hamming'], [1.0]], ['control: N=1 fc=1 hann', [1, '1', 'hann'], [1.0]], ['control: N=1 fc=1 rect', [1, '1', 'rect'], [1.0]]], [['regression: N=5 fc=1/4 hamming', [5, '1/4', 'hamming'], [0.02455383, 0.23438946, 0.4821134, 0.23438946, 0.02455383]], ['regression: N=5 fc=1/4 hann', [5, '1/4', 'hann'], [0.0, 0.23688591, 0.52622818, 0.23688591, 0.0]], ['repair check: N=4 fc=1 hamming', [4, '1', 'hamming'], [-0.01793722, 0.51793722, 0.51793722, -0.01793722]], ['control: N=2 fc=1/2 hamming', [2, '1/2', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=1/2 rect', [2, '1/2', 'rect'], [0.5, 0.5]], ['control: N=2 fc=1/4 hamming', [2, '1/4', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=1/4 rect', [2, '1/4', 'rect'], [0.5, 0.5]]], [['regression: N=5 fc=3/5 hamming', [5, '3/5', 'hamming'], [-0.00820621, 0.17925211, 0.65790821, 0.17925211, -0.00820621]], ['regression: N=5 fc=3/5 hann', [5, '3/5', 'hann'], [0.0, 0.16767497, 0.66465005, 0.16767497, 0.0]], ['regression: N=5 fc=1/2 hamming', [5, '1/2', 'hamming'], [0.0, 0.20371237, 0.59257526, 0.20371237, 0.0]], ['control: N=2 fc=3/5 hamming', [2, '3/5', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=3/5 rect', [2, '3/5', 'rect'], [0.5, 0.5]], ['control: N=2 fc=1 hamming', [2, '1', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=1 rect', [2, '1', 'rect'], [0.5, 0.5]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: N=4 fc=1/2 hamming | [0.03857901, 0.46142099, 0.46142099, 0.03857901] | [0.0167364, 0.4832636, 0.4832636, 0.0167364] | Failed |
| regression: N=4 fc=1/2 rect | [0.22295145, 0.27704855, 0.27704855, 0.22295145] | [0.125, 0.375, 0.375, 0.125] | Failed |
| regression: N=4 fc=1/4 hamming | [0.04488511, 0.45511489, 0.45511489, 0.04488511] | [0.03857901, 0.46142099, 0.46142099, 0.03857901] | Failed |
| control: N=1 fc=1/2 hamming | [1.0] | [1.0] | Passed |
| control: N=1 fc=1/2 hann | [1.0] | [1.0] | Passed |
| control: N=1 fc=1/2 rect | [1.0] | [1.0] | Passed |
| control: N=1 fc=1/4 hamming | [1.0] | [1.0] | Passed |
SHA-256 / a7217c75ad1f752a078ff8159f434107a7259ad768f4b91b80addd7fda6bfee9
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
N, fc_s, win = x
fc = float(Fraction(fc_s))
if N < 1 or not 0 < fc <= 1:
return 'bad-spec'
c = (N - 1) / 2
taps = []
for n in range(N):
t = n - c
s = 1.0 if t == 0 else math.sin(math.pi * fc * t) / (math.pi * fc * t)
if N == 1 or win == 'rect':
w = 1.0
elif win == 'hann':
w = 0.5 - 0.5 * math.cos(2 * math.pi * n / (N - 1))
else:
w = 0.54 - 0.46 * math.cos(2 * math.pi * n / (N - 1))
taps.append(fc * s * w)
tot = sum(taps)
return [round(v / tot, 8) + 0.0 for v in taps]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: N=4 fc=1/2 hamming', [4, '1/2', 'hamming'], [0.0167364, 0.4832636, 0.4832636, 0.0167364]], ['regression: N=4 fc=1/2 rect', [4, '1/2', 'rect'], [0.125, 0.375, 0.375, 0.125]], ['regression: N=4 fc=1/4 hamming', [4, '1/4', 'hamming'], [0.03857901, 0.46142099, 0.46142099, 0.03857901]], ['control: N=1 fc=1/2 hamming', [1, '1/2', 'hamming'], [1.0]], ['control: N=1 fc=1/2 hann', [1, '1/2', 'hann'], [1.0]], ['control: N=1 fc=1/2 rect', [1, '1/2', 'rect'], [1.0]], ['control: N=1 fc=1/4 hamming', [1, '1/4', 'hamming'], [1.0]]], [['regression: N=4 fc=1/4 rect', [4, '1/4', 'rect'], [0.22295145, 0.27704855, 0.27704855, 0.22295145]], ['regression: N=4 fc=3/5 hamming', [4, '3/5', 'hamming'], [0.00652778, 0.49347222, 0.49347222, 0.00652778]], ['regression: N=4 fc=1/4 hamming', [4, '1/4', 'hamming'], [0.03857901, 0.46142099, 0.46142099, 0.03857901]], ['control: N=1 fc=1/4 hann', [1, '1/4', 'hann'], [1.0]], ['control: N=1 fc=1/4 rect', [1, '1/4', 'rect'], [1.0]], ['control: N=1 fc=3/5 hamming', [1, '3/5', 'hamming'], [1.0]], ['control: N=1 fc=3/5 hann', [1, '3/5', 'hann'], [1.0]]], [['regression: N=5 fc=1/2 hamming', [5, '1/2', 'hamming'], [0.0, 0.20371237, 0.59257526, 0.20371237, 0.0]], ['regression: N=5 fc=1/2 hann', [5, '1/2', 'hann'], [0.0, 0.19449226, 0.61101547, 0.19449226, 0.0]], ['regression: N=4 fc=3/5 hamming', [4, '3/5', 'hamming'], [0.00652778, 0.49347222, 0.49347222, 0.00652778]], ['control: N=1 fc=3/5 rect', [1, '3/5', 'rect'], [1.0]], ['control: N=1 fc=1 hamming', [1, '1', 'hamming'], [1.0]], ['control: N=1 fc=1 hann', [1, '1', 'hann'], [1.0]], ['control: N=1 fc=1 rect', [1, '1', 'rect'], [1.0]]], [['regression: N=5 fc=1/4 hamming', [5, '1/4', 'hamming'], [0.02455383, 0.23438946, 0.4821134, 0.23438946, 0.02455383]], ['regression: N=5 fc=1/4 hann', [5, '1/4', 'hann'], [0.0, 0.23688591, 0.52622818, 0.23688591, 0.0]], ['repair check: N=4 fc=1 hamming', [4, '1', 'hamming'], [-0.01793722, 0.51793722, 0.51793722, -0.01793722]], ['control: N=2 fc=1/2 hamming', [2, '1/2', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=1/2 rect', [2, '1/2', 'rect'], [0.5, 0.5]], ['control: N=2 fc=1/4 hamming', [2, '1/4', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=1/4 rect', [2, '1/4', 'rect'], [0.5, 0.5]]], [['regression: N=5 fc=3/5 hamming', [5, '3/5', 'hamming'], [-0.00820621, 0.17925211, 0.65790821, 0.17925211, -0.00820621]], ['regression: N=5 fc=3/5 hann', [5, '3/5', 'hann'], [0.0, 0.16767497, 0.66465005, 0.16767497, 0.0]], ['regression: N=5 fc=1/2 hamming', [5, '1/2', 'hamming'], [0.0, 0.20371237, 0.59257526, 0.20371237, 0.0]], ['control: N=2 fc=3/5 hamming', [2, '3/5', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=3/5 rect', [2, '3/5', 'rect'], [0.5, 0.5]], ['control: N=2 fc=1 hamming', [2, '1', 'hamming'], [0.5, 0.5]], ['control: N=2 fc=1 rect', [2, '1', 'rect'], [0.5, 0.5]]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: N=4 fc=1/2 hamming | [0.0167364, 0.4832636, 0.4832636, 0.0167364] | [0.0167364, 0.4832636, 0.4832636, 0.0167364] | Passed |
| regression: N=4 fc=1/2 rect | [0.125, 0.375, 0.375, 0.125] | [0.125, 0.375, 0.375, 0.125] | Passed |
| regression: N=4 fc=1/4 hamming | [0.03857901, 0.46142099, 0.46142099, 0.03857901] | [0.03857901, 0.46142099, 0.46142099, 0.03857901] | Passed |
| control: N=1 fc=1/2 hamming | [1.0] | [1.0] | Passed |
| control: N=1 fc=1/2 hann | [1.0] | [1.0] | Passed |
| control: N=1 fc=1/2 rect | [1.0] | [1.0] | Passed |
| control: N=1 fc=1/4 hamming | [1.0] | [1.0] | Passed |
SHA-256 / 8b745303584f8b9e2d164dc3c0f6fe41010b13ebfc0b0702e1b4ef8bcf5c541f
Verification & scope
A deterministic bounded teaching model with a stipulated toy contract; exact rational arithmetic or fixed-decimal rounding keeps outputs strict JSON. It is not a production DSP library and claims no standards conformance. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:51:36.698016+00:00.
Case digest / cde44a84d96b5280a128e8a9f057535214f5aae5a39961f59e3623bfd4fa094c