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:
- Zero‑pad signal and kernel to at least M+N‑1
- FFT both
- Pointwise multiply spectra
- 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