43.4 Windowing and Applications

Windowing reduces spectral leakage; apply before FFT for better frequency resolution.


43.4.1 Common Window Functions

void applyHann(float[] x, int N) {
  for (int n = 0; n < N; n++) {
    float w = 0.5f * (1f - (float)Math.cos(2*Math.PI*n/(N-1)));
    x[2*n] *= w; x[2*n+1] *= w;
  }
}

void applyHamming(float[] x, int N) {
  for (int n = 0; n < N; n++) {
    float w = 0.54f - 0.46f * (float)Math.cos(2*Math.PI*n/(N-1));
    x[2*n] *= w; x[2*n+1] *= w;
  }
}

43.4.2 Spectral Power

float[] spectralPower(float[] spectrum, int N) {
  float[] power = new float[N/2+1];
  for (int k = 0; k <= N/2; k++) {
    float re = spectrum[2*k], im = spectrum[2*k+1];
    power[k] = re*re + im*im;
  }
  return power;
}

43.4.3 Convolution via FFT

For large kernels, convolution is faster in frequency domain:

  1. Zero‑pad signal and kernel to at least M+N‑1
  2. FFT both
  3. Pointwise multiply spectra
  4. IFFT result
void convolveFFT(float[] signal, int M, float[] kernel, int N, float[] out) {
  int len = Integer.highestOneBit(M+N-1) << 1; // next power of 2
  float[] s = new float[len*2], k = new float[len*2];
  for (int i = 0; i < M; i++) s[2*i] = signal[i];
  for (int i = 0; i < N; i++) k[2*i] = kernel[i];
  fftRadix2(s, len); fftRadix2(k, len);
  for (int i = 0; i < len; i++) Complex.mul(s, 2*i, k, 2*i, s, 2*i);
  ifft(s, len);
  for (int i = 0; i < M+N-1; i++) out[i] = s[2*i];
}

43.4.4 Use Cases

  • Audio analysis: pitch detection, spectrograms
  • Filtering: lowpass/highpass via frequency masking
  • Image processing: 2D FFT for convolution