FIR filter design by windowed sinc

Published 11 September 2026 · Updated 11 September 2026 · 15 min read

Filter magnitude-response illustration
A linear-phase FIR magnitude response, designed by the windowed-sinc method.

Most FIR filters in real systems are three numbers and a window: a cutoff, a tap count, and a choice from the window table. Getting from those to a coefficient list does not require a design package, and understanding what each of the three decides is what stops a filter from being over-built by a factor of four in tap count.

The generator below designs low-pass, high-pass, band-pass and band-stop filters and measures what the result actually achieves — transition width, stopband attenuation, passband ripple and group delay — rather than quoting a rule of thumb.

Windowed-sinc FIR coefficient generator

Linear phase throughout. Taps are symmetric; the group delay is always (N − 1)/2 samples.

High-pass and band-stop need an odd count.
The −6 dB point lands here for every window.
Taps needed for that width are reported below.
Taps & order
Group delay
Measured transition width
Taps for the target width
Stopband attenuation
Passband ripple
Ripple predicted from the attenuation
−6 dB check at the cutoff
DC / Nyquist gain
Peak tap

Impulse response (the coefficients)

Magnitude response

First coefficients

Transition width, attenuation and ripple are measured on the equivalent low-pass design with the same length and window, sited at the cutoff for a high-pass and at the upper edge for the band types. Spectral inversion swaps the passband and the stopband but leaves those figures intact.

The ideal filter cannot be built

The brick-wall low-pass has an impulse response of 2fc/fs · sinc(2fcn/fs), which is infinite in both directions, decays only as 1/n, and is therefore neither buildable nor causal. Any practical design is that response multiplied by something finite — and the choice of that something is the entire subject.

Multiplying by a rectangle is the obvious first attempt: take N taps and stop. It is also the worst choice, because a rectangle in the time domain is a sinc in the frequency domain, and the resulting ripple never decays — the Gibbs phenomenon. The fix is to multiply by a smoother window, which trades transition width for attenuation.

One consistency check worth knowing before anything else: the ideal sinc sums to exactly 1 over all samples, so a low-pass designed this way has a DC gain of 1. Cut that series at 4001 taps with a cutoff at 0.05 × fs and the sum comes to 0.99899 — the 0.1% that the truncation left behind, which is precisely what the window is there to clean up.

The recipe

  1. Choose the cutoff. The design crosses −6 dB at that frequency for every window in the table, which makes the cutoff self-checking: if the measured response at fc is not −6.0 dB, something is wrong with the design rather than with your expectation.
  2. Choose the window from the attenuation you need.
  3. Choose N from the transition width you need, using the measured constant below: N ≈ K · fs/Δf. Always round up, and prefer odd N.
  4. Multiply the ideal sinc by the symmetric window and normalise the passband gain. The symmetric definition (denominator N − 1) is the right one here; the periodic definition from the window article is for DFTs.

The trade-off, measured

These are measured from designs at 48 kHz with a 1000 Hz transition, 257 taps for the constant and the stated tap count for the build. The constant is the transition width in units of fs/N, so it is the number to divide by when sizing a filter.

Window Transition constant Taps for 1 kHz Stopband attenuation Passband ripple
Rectangular1.2259−21.0 dB0.65 dB
Hann3.36163−43.9 dB0.055 dB
Hamming3.51169−54.2 dB0.020 dB
Blackman6.02291−75.3 dB0.001 dB
Blackman-Harris8.03387−109.4 dB< 0.001 dB
Nuttall8.03387−112.0 dB< 0.001 dB
Blackman-Nuttall8.03387−115.1 dB< 0.001 dB
Flat-top10.04483−114.9 dB< 0.001 dB

The constants are stable: across an eight-fold range of tap counts (33 to 257) the Hann constant varies by less than 3%, so N = K · fs/Δf is a usable design rule rather than a coincidence. Asking for a 1000 Hz transition at 48 kHz gave 169 taps for Hamming, and the design measured 990 Hz — 1% over the request.

Ripple and attenuation are the same number

For a windowed-sinc design the passband ripple and the stopband attenuation are not independent: they are the same amplitude expressed two different ways. If the stopband sits A dB down, the passband deviates by approximately

ΔAdB ≈ 8.686 · 10−A/20

Check it against the table: Hann's −43.9 dB becomes 8.686 × 10−43.9/20 = 0.055 dB, and the measured passband ripple is 0.055 dB. Hamming predicts 0.017 dB against 0.020 measured, Blackman 0.0015 against 0.001, and rectangular 0.77 against 0.65. That is why a filter with a deep stopband automatically has a flat passband, and why asking for both a narrow transition and 100 dB of attenuation is expensive rather than impossible.

It also corrects a widely repeated mistake: the stopband attenuation of the design is better than the window's peak sidelobe level, because that peak sits inside the transition band and is never part of the stopband. Hann is the clearest case — the window's first sidelobe is −31.5 dB, and the filter reaches −43.9 dB. The measured figures here also reproduce the classical design-table values for FIR work (rectangular −21, Hann −44, Hamming −53, Blackman −74 dB) to within about 1 dB, which is a useful confirmation that the window really is the same window.

Linear phase, and the delay nobody accounts for

Every filter here is symmetric about its centre tap, so its phase response is exactly linear — the test behind this page reproduces φ(f) = −π(N−1)f/fs to 4×10−16 rad. All frequencies are delayed by the same amount, (N − 1)/2 samples, and that delay is not a side effect to be ignored:

td = (N − 1) / (2 fs)

A 201-tap filter at 48 kHz delays by 100 samples, which is 2.083 ms — the same time a sound takes to travel 71 cm. Align two channels with mismatched FIR filters and you have built a 71 cm path difference into your measurement. That, and not the magnitude response, is why crossover and measurement filters need their delay accounted for explicitly.

High-pass, band-pass and band-stop

A high-pass is a low-pass subtracted from a unit impulse, a trick called spectral inversion. It follows that the tap count must be odd: the unit impulse has to land on a real sample, and only an odd-length array has an integer centre. Passing N = 100 to a high-pass design is not a small inaccuracy, it is a different filter, so the generator refuses it rather than silently rounding.

A band-pass is the difference of two low-passes, which the algebra collapses into a sinc multiplied by a cosine at the band centre:

h[n] = 2Δ · sinc(Δ · (n − M)) · cos(2πf0(n − M)/fs)

with Δ = (f2 − f1)/fs and f0 the band centre. Note that the sinc argument carries Δ and not 2Δ — the factor of two belongs to the leading term only. Getting that wrong doubles the passband, which looks plausible on a plot until you check the edges. The generator's test suite verifies the closed form against a difference of two low-passes to 2.8×10−17.

Band-stop is the same construction inverted, and needs odd N for the same reason high-pass does.

Five mistakes worth avoiding

  1. Confusing taps with order. An N-tap filter has order N − 1 and a group delay of (N − 1)/2 samples. Mixing the two up halves or doubles your delay compensation.
  2. Leaving the group delay out of the alignment. Two milliseconds is not negligible in a measurement chain.
  3. Expecting a brick wall. A Hann-windowed 101-tap filter at 48 kHz spends about 1.6 kHz getting from passband to stopband. Using the cutoff as if it were the edge of the passband is how signals get attenuated that you thought were inside the band.
  4. Quoting the window's sidelobe level as the filter's attenuation. Hann gives −43.9 dB, not −31.5 dB — a 12 dB error in the safe direction, but an error.
  5. Designing a high-pass with an even tap count. The impulse has nowhere to land.

Sizing a filter in one line

Decide the attenuation you need, pick the window from the table, then compute N = K · fs/Δf and round up to the next odd number. For a 48 kHz system with a 2 kHz transition and 55 dB of attenuation needed, Hamming's constant gives 169 taps and the design delivers −54.2 dB — close enough that the next step up to Blackman (291 taps) is usually unnecessary. That decision is the whole point of knowing the table rather than guessing.

Coefficients here are engineering aids rather than measurements; verify the design in your own toolchain before shipping it. See the disclaimer and the tool index.