Lanczos window (impl.)

This is the implementation guide for the Lanczos window. For theoretical background, including mathematical formula, frequency response, and spectral analysis, see the the article on Lanczos window.

All code examples are written in C for maximum performance and portability.


Direct Implementation

The following function computes the Lanczos window value for a given sample index n and total window length N. The Lanczos window is the central lobe of the sinc function, providing excellent sidelobe suppression.


#include <math.h>

/**
 * Compute Lanczos window coefficient for a single sample.
 *
 * @param n     Sample index (0 to N-1)
 * @param N     Total window length
 * @return      Window coefficient (0.0 to 1.0)
 */
double lanczos_window_sample(int n, int N) {
    if (N <= 1) return 1.0;
    if (n < 0 || n >= N) return 0.0;
    
    double m = (N - 1) / 2.0;
    double t = (n - m) / m;
    
    if (t == 0.0) return 1.0;
    if (fabs(t) >= 1.0) return 0.0;
    
    return sin(M_PI * t) / (M_PI * t);
}

Full Array Implementation

For better performance when the entire window is needed, the following function fills a pre-allocated array with all coefficients at once.


#include <math.h>
#include <stdlib.h>

/**
 * Generate full Lanczos window array.
 *
 * @param N     Length of the window (number of samples)
 * @param out   Output array of length N (must be pre-allocated)
 */
void lanczos_window_array(int N, double *out) {
    if (N <= 0) return;
    
    if (N == 1) {
        out[0] = 1.0;
        return;
    }
    
    double m = (N - 1) / 2.0;
    
    for (int i = 0; i < N; i++) {
        double t = (i - m) / m;
        
        if (t == 0.0) {
            out[i] = 1.0;
        } else if (fabs(t) >= 1.0) {
            out[i] = 0.0;
        } else {
            out[i] = sin(M_PI * t) / (M_PI * t);
        }
    }
}

Optimized Implementation (with sinc approximation)

For performance-critical applications, here is an optimized version with explicit zero handling:


/**
 * Generate full Lanczos window array (optimized).
 *
 * @param N     Length of the window (number of samples)
 * @param out   Output array of length N (must be pre-allocated)
 */
void lanczos_window_array_opt(int N, double *out) {
    if (N <= 0) return;
    
    if (N == 1) {
        out[0] = 1.0;
        return;
    }
    
    const double m = (N - 1) / 2.0;
    const double inv_m = 1.0 / m;
    const double inv_pi = 1.0 / M_PI;
    
    for (int i = 0; i < N; i++) {
        double t = (i - m) * inv_m;
        
        if (t == 0.0) {
            out[i] = 1.0;
        } else if (fabs(t) >= 1.0) {
            out[i] = 0.0;
        } else {
            double arg = M_PI * t;
            out[i] = sin(arg) * inv_pi / t;
        }
    }
}

Usage Example

The following example demonstrates how to apply the Lanczos window to a real signal.


#include <stdio.h>
#include <math.h>

#define N 512

int main() {
    double window[N];
    double signal[N];
    double windowed[N];
    
    /* Generate Lanczos window */
    lanczos_window_array(N, window);
    
    /* Generate test signal (sinusoid with non-integer period) */
    for (int i = 0; i < N; i++) {
        signal[i] = sin(2 * M_PI * i / 9.5);
    }
    
    /* Apply window to signal */
    for (int i = 0; i < N; i++) {
        windowed[i] = signal[i] * window[i];
    }
    
    /* Print first 10 samples */
    printf("n    window      signal      windowed\n");
    for (int i = 0; i < 10; i++) {
        printf("%d    %.6f    %.6f    %.6f\n", 
               i, window[i], signal[i], windowed[i]);
    }
    
    return 0;
}

Expected Output (first 5 samples, N=512)

n    window      signal      windowed
0    0.000000    0.000000    0.000000
1    0.000024    0.647387    0.000016
2    0.000096    0.998351    0.000096
3    0.000216    0.907575    0.000196
4    0.000384    0.460073    0.000177

Implementation Notes

  • Sinc-based shape: The Lanczos window is the central lobe of the normalized sinc function.
  • Zero at endpoints: The window tapers exactly to zero at n=0 and n=N-1.
  • Regular zero-crossings: The window has zero-crossings at regular intervals due to the sinc function.
  • First sidelobe: Approximately -58 dB – better than Parzen (-40 dB) and Bohman (-46 dB).
  • Main lobe width: Approximately 0.10–0.11 normalized frequency.
  • Roll-off rate: Moderate at approximately 12 dB per octave.
  • Symmetry: The window is perfectly symmetric: w[n] = w[N-1-n] for all n.
  • Special case: When t = 0, the sinc function is defined as 1 (limit value).
  • Edge case N=1: The only coefficient is 1.0.
  • Precomputation: For real-time applications, precompute the window once and reuse it for multiple signal blocks.

Alternative: Precomputed Lookup Table

For embedded systems or when speed is critical, precompute the window at compile time:


#define N 512

static const double LANCZOS_WINDOW[N] = {
    0.000000, 0.000024, 0.000096, 0.000216, 0.000384, /* ... */
    /* Full table would be generated by a script */
};

/* Usage */
for (int i = 0; i < N; i++) {
    windowed[i] = signal[i] * LANCZOS_WINDOW[i];
}

Comparison with Other Windows

Window              Main lobe    First sidelobe    Roll-off    Best for
Rectangular         0.04         -13 dB            ~6 dB/oct   Resolution
Hann                0.08         -31 dB            ~18 dB/oct  General
Hamming             0.08         -41 dB            ~6 dB/oct   General
Parzen              0.09         -40 dB            Fast        Balance
Bohman              0.13         -46 dB            ~18 dB/oct  High dynamic range
Lanczos             0.11         -58 dB            ~12 dB/oct  Interpolation
Blackman            0.12         -58 dB            ~18 dB/oct  Leakage suppression

When to Use Lanczos

  • Excellent first sidelobe: -58 dB – significantly better than Parzen and Bohman.
  • Resampling and interpolation: The Lanczos window is commonly used with the Lanczos kernel for image resampling.
  • Anti-aliasing: Smooth transition characteristics make it suitable for anti-aliasing filters.
  • Spectral analysis: Good balance between main lobe width and nearby leakage suppression.

Lanczos vs Blackman

Characteristic       Lanczos               Blackman
First sidelobe       -58 dB                -58 dB
Main lobe width      0.11                  0.12
Roll-off             ~12 dB/octave         ~18 dB/octave
Computation          sin() / division      cos() terms only
Best when            Interpolation         General spectral analysis

See also: The Lanczos Window in DSP