Nuttall Window (impl.)

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

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


Direct Implementation

The following function computes the Nuttall window value for a given sample index n and total window length N. The Nuttall window is a 4-term cosine window with optimized coefficients for excellent sidelobe suppression.


#include <math.h>

/**
 * Compute Nuttall 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 nuttall_window_sample(int n, int N) {
    if (N <= 1) return 1.0;
    if (n < 0 || n >= N) return 0.0;
    
    /* Nuttall window coefficients (4-term) */
    const double a0 = 0.355768;
    const double a1 = 0.487396;
    const double a2 = 0.144232;
    const double a3 = 0.012604;
    
    double angle = 2 * M_PI * n / (N - 1);
    
    return a0
           - a1 * cos(angle)
           + a2 * cos(2 * angle)
           - a3 * cos(3 * angle);
}

Alternative Implementation (Blackman–Nuttall)

A common variant is the Blackman–Nuttall window, which has slightly different coefficients:


/**
 * Compute Blackman–Nuttall window coefficient.
 *
 * @param n     Sample index (0 to N-1)
 * @param N     Total window length
 * @return      Window coefficient
 */
double blackman_nuttall_window_sample(int n, int N) {
    if (N <= 1) return 1.0;
    if (n < 0 || n >= N) return 0.0;
    
    /* Blackman–Nuttall window coefficients */
    const double a0 = 0.3635819;
    const double a1 = 0.4891775;
    const double a2 = 0.1365995;
    const double a3 = 0.0106411;
    
    double angle = 2 * M_PI * n / (N - 1);
    
    return a0
           - a1 * cos(angle)
           + a2 * cos(2 * angle)
           - a3 * cos(3 * angle);
}

Alternative Implementation (Minimum 4-Term)

This variant provides the minimum possible sidelobe level for a 4-term cosine window:


/**
 * Compute minimum 4-term Nuttall window coefficient.
 *
 * @param n     Sample index (0 to N-1)
 * @param N     Total window length
 * @return      Window coefficient
 */
double nuttall_min4_window_sample(int n, int N) {
    if (N <= 1) return 1.0;
    if (n < 0 || n >= N) return 0.0;
    
    /* Minimum 4-term Nuttall coefficients */
    const double a0 = 0.3635819;
    const double a1 = 0.4891775;
    const double a2 = 0.1365995;
    const double a3 = 0.0106411;
    
    double angle = 2 * M_PI * n / (N - 1);
    
    return a0
           - a1 * cos(angle)
           + a2 * cos(2 * angle)
           - a3 * cos(3 * 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 Nuttall window array.
 *
 * @param N     Length of the window (number of samples)
 * @param out   Output array of length N (must be pre-allocated)
 */
void nuttall_window_array(int N, double *out) {
    if (N <= 0) return;
    
    if (N == 1) {
        out[0] = 1.0;
        return;
    }
    
    const double a0 = 0.355768;
    const double a1 = 0.487396;
    const double a2 = 0.144232;
    const double a3 = 0.012604;
    
    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)
               - a3 * cos(3 * angle);
    }
}

Full Array Implementation (Blackman–Nuttall)


/**
 * Generate full Blackman–Nuttall window array.
 *
 * @param N     Length of the window (number of samples)
 * @param out   Output array of length N (must be pre-allocated)
 */
void blackman_nuttall_window_array(int N, double *out) {
    if (N <= 0) return;
    
    if (N == 1) {
        out[0] = 1.0;
        return;
    }
    
    const double a0 = 0.3635819;
    const double a1 = 0.4891775;
    const double a2 = 0.1365995;
    const double a3 = 0.0106411;
    
    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)
               - a3 * cos(3 * angle);
    }
}

Usage Example

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


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

#define N 64

int main() {
    double window[N];
    double signal[N];
    double windowed[N];
    
    /* Generate Nuttall window */
    nuttall_window_array(N, window);
    
    /* Generate test signal (sinusoid) */
    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=64)

n    window      signal      windowed
0    0.000004    0.000000    0.000000
1    0.000018    0.647387    0.000012
2    0.000147    0.998351    0.000147
3    0.000453    0.907575    0.000411
4    0.001002    0.460073    0.000461

Implementation Notes

  • Albert Nuttall: The window is named after Albert H. Nuttall, who published the optimal coefficients for cosine-sum windows.
  • 4-term design: The Nuttall window uses 4 cosine terms, providing excellent sidelobe suppression.
  • Sidelobe level: Approximately -93 dB (standard) or -98 dB (Blackman–Nuttall) – exceptional performance.
  • Main lobe width: Approximately 0.16 normalized frequency – moderately wide.
  • Continuous derivatives: The window has continuous first and second derivatives at the boundaries.
  • Endpoints: Values at endpoints are very close to zero (not exactly zero).
  • Symmetry: The window is perfectly symmetric: w[n] = w[N-1-n] for all n.
  • Optimal coefficients: The coefficients are optimized to minimize the peak sidelobe level.
  • 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 64

static const double NUTTALL_WINDOW[N] = {
    0.000004, 0.000018, 0.000147, 0.000453, 0.001002, /* ... */
    /* Full table would be generated by a script */
};

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

Nuttall vs Other 4-Term Windows

The Nuttall family of windows includes several 4-term cosine windows:

Window                 a0        a1        a2        a3        Sidelobe (dB)
Nuttall (standard)     0.355768  0.487396  0.144232  0.012604  -93.3
Blackman–Nuttall       0.363582  0.489178  0.136600  0.010641  -98.2
Minimum 4-term         0.363582  0.489178  0.136600  0.010641  -98.2

Comparison with Cosine Windows

Window              Terms    Sidelobe (dB)    Main lobe    Best for
Hann                2        -31              ~0.08        General purpose
Hamming             2        -41              ~0.08        General purpose
Blackman            3        -58              ~0.12        Leakage suppression
Blackman–Harris     4        -92              ~0.16        High dynamic range
Nuttall             4        -93              ~0.16        High dynamic range
Flat Top            5        -80 to -90       ~0.20        Amplitude accuracy

Comparison with Blackman–Harris

Characteristic       Blackman–Harris         Nuttall
Peak sidelobe        -92.0 dB                -93.3 dB
Roll-off rate        ~6 dB/octave            ~18 dB/octave
Main lobe width      ~0.16                   ~0.16
Coefficients         (0.35875, 0.48829,      (0.355768, 0.487396,
                      0.14128, 0.01168)       0.144232, 0.012604)
Best when            Fast roll-off needed    Minimum peak sidelobe

Practical Applications

Application                       Why Nuttall?
High-dynamic-range spectrum        Excellent sidelobe suppression
EMI/EMC testing                   Needs low spectral leakage
Precision metrology               High measurement accuracy
Scientific instrumentation        Demands clean spectral estimation
Audio analysis                    Good balance of properties

See also: The Nuttall Window in DSP