Blackman window (impl.)

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

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


Direct Implementation

The following function computes the Blackman window value for a given sample index n and total window length N. The window uses three cosine terms for superior sidelobe suppression.


#include <math.h>

/**
 * Compute Blackman 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 blackman_window_sample(int n, int N) {
    if (N <= 1) return 1.0;
    if (n < 0 || n >= N) return 0.0;
    
    const double a0 = 0.42;
    const double a1 = 0.5;
    const double a2 = 0.08;
    
    double angle = 2 * M_PI * n / (N - 1);
    
    return a0 - a1 * cos(angle) + a2 * cos(2 * angle);
}

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 Blackman window array.
 *
 * @param N     Length of the window (number of samples)
 * @param out   Output array of length N (must be pre-allocated)
 */
void blackman_window_array(int N, double *out) {
    if (N <= 0) return;
    
    if (N == 1) {
        out[0] = 1.0;
        return;
    }
    
    const double a0 = 0.42;
    const double a1 = 0.5;
    const double a2 = 0.08;
    
    for (int i = 0; i < N; i++) {
        double angle = 2 * M_PI * i / (N - 1);
        out[i] = a0 - a1 * cos(angle) + a2 * cos(2 * angle);
    }
}

Usage Example

The following example demonstrates how to apply the Blackman 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 Blackman window
    blackman_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\twindow\tsignal\t\twindowed\n");
    for (int i = 0; i < 10; i++) {
        printf("%d\t%.6f\t%.6f\t%.6f\n", 
               i, window[i], signal[i], windowed[i]);
    }
    
    return 0;
}

Expected Output (first 5 samples)

n	window	signal		windowed
0	0.000000	0.000000	0.000000
1	0.000049	0.647387	0.000032
2	0.000195	0.998351	0.000195
3	0.000437	0.907575	0.000397
4	0.000774	0.460073	0.000356

Implementation Notes

  • Coefficients: The Blackman window uses a0 = 0.42, a1 = 0.5, and a2 = 0.08, which provides a first sidelobe level of approximately -58 dB.
  • Three cosine terms: Unlike Hann (2 terms) and Hamming (2 terms), the Blackman window uses three terms for superior sidelobe suppression.
  • Endpoints: The window tapers to exactly zero at both ends (n=0 and n=N-1).
  • Symmetry: The window is perfectly symmetric: w[n] = w[N-1-n] for all n.
  • 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 BLACKMAN_WINDOW[N] = {
    0.000000, 0.000049, 0.000195, 0.000437, 0.000774, /* ... */
    /* Full table would be generated by a script */
};

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

Comparison of Cosine Windows

The following table compares the three cosine-based windows implemented in this series:

Window      a0      a1      a2      First sidelobe   Endpoint value
Hann        0.50    0.50    -       -31 dB           0.000
Hamming     0.54    0.46    -       -41 dB           0.080
Blackman    0.42    0.50    0.08    -58 dB           0.000