# Reducing the number of data points of an FFT

I'm in an odd situation where an FFT is giving me too much data to process. I'm performing an FFT on audio sampled at 500 Hz, over 30 seconds. The result is 7500 bins of useful information, however I don't need this sort of resolution. I still need to see frequencies up to 250 Hz so I can't reduce the sampling rate. I also need information from the entire sample, so I can't use less than 30 seconds of data either.

What can I do to reduce the number of points, but keep the magnitude and phase information relatively intact? I would prefer not to throw away points, is it possible to take an average of x points?

• for 7500 samples i would not lift a finger to reduce the data. just zero-pad it to 8192 and FFT the son-o-va-bitch. bins 0 to 4096 take you from DC to 500 Hz in approximately $\tfrac{1}{10}$ Hz steps. now when you have a time-domain signal that is, say, $2^{30}$ samples long, you might have a problem FFTing that whole thing. then you have to split it up or decimate it. – robert bristow-johnson May 8 '17 at 4:28
• It's not the FFT stage that is the problem, it's what I need to do with the result afterwards. – Lukeyb May 8 '17 at 5:17
• you will have 4096 frequency bins which have magnitude and phase for each frequency component. you can discard the ones you don't need. – robert bristow-johnson May 8 '17 at 5:37
• So what DO you need to do with the data? The best method (smoothing, averaging, principal components, perceptual modeling, etc) really depends on the requirements of your application – Hilmar May 8 '17 at 12:52

Just as one can low-pass filter and decimate in the time domain if you don't need the point density, you can also "low-pass" filter the complex FFT result or frequency domain vector and then decimate to a reduced number of spectrum samples.

Convolution with a Sinc kernel of sufficient width is a suitable low-pass and pre-decimation averaging filter in either domain.

Do you want to know specific frequencies? Go for the Goertzel algorithm.

Do you need to know every 2nd frequency? This corresponds to downsampling in the frequency domain, which is aliasing in time domain. You can do it like this (where I have reduced the sampling rate and signal duration for better plotting, obviously it also works with 30s and 500Hz):

Fs = 50 # 50 Hz for less data
x = np.random.randn(2*Fs)  # The audio signal: 2s for less data for better plotting here
L = len(x)

# Calculate full FFT for reference
X = np.fft.fft(x)
f1 = np.linspace(0, Fs, L, endpoint=False)

# Calculate every 2nd sample of FFT
x2 = x[:L/2] + x[L/2:] # Perform the aliasing operation in time domain
X2 = np.fft.fft(x2)
f2 = np.linspace(0, Fs, L/2, endpoint=False)

plt.plot(f2, abs(X2), 'go-')
plt.plot(f1, abs(X), 'rx-')

plt.xlim((0, Fs/2))


Obviously, the approach of aliasing also works for every Nth sample in general, if $L$ can be divided by $N$ without remainder.

• I'll edit my question to be more clear, I've thought about taking every xth frequency but I would like to avoid throwing away information like that if possible. I suppose I'm more looking for an averaging approach... – Lukeyb May 8 '17 at 4:02