I am attempting to build a 'live' FFT for continuous analysis of an audio signal. I am relatively new to this, but have attempted the full thing, and then updating the graph at 20Hz refresh rate. My FFT is working with regards to identifying the correct frequencies, however is very 'jumpy' with regards to the amplitude. Before I analyse my code to see where I have gone wrong, I would like to just confirm the process I have used is correct.

  1. Read audio samples into circular buffer.

  2. Read half of the window size from last half of previously processed array. (50% because I am trying to achieve 50% overlap).

  3. Read half of the window size from the buffer to give the complete window size.

  4. Perform Window Function on the window to process.

  5. Zero pad the end of this to achieve a n^2 bit FFT Size.

  6. Perform FFT on the full array

  7. Save Array to List of arrays to average (add to end, delete first one to always retain x no. of averages).

  8. Average the arrays in List of arrays (treat real and imaginary values as two independent values when averaging).

  9. Obtain the magnitude for each bin in the averaged array by obtaining the square root of the imaginary^2 + real^2. This is then divided by the number of bins, and the entire value multiplied by 2 as we have halved the FFT spectrum to only look at the positive values. This is then multiplied by a window correction factor.

  10. This thread should then sleep for however long it takes to capture half the window length needed (the next set of audio samples) subtract the computational time to perform this FFT step.

That is currently the method I am working to. I know my FFT algorithm is good as I have tested it on known input and output values. I am sure it is a coding mistake, but as this is my first project I wanted to check that the overall method I am following is sound. If anyone can see any potential issues, please let me know. Thanks.

  • 1
    You probably meant a 2^n FFT size? – MSalters Jun 14 at 20:15
  • Hi! If you really think that you have a programming mistake, then please post a sufficient piece of code excerpt as well. In fact, you could also put some data, probably a few snapshots, plots, figures, etc. so that people could indeed see and reproduce the same problem that you observed... – Fat32 Jun 14 at 22:31

There are numerous ways to do this and you have the general flow except, as noted, complex averaging is only done in special circumstance, which you haven’t mentioned and are in most cases not applicable.

One can average magnitude or magnitude squared. There is a 1975 Bell System Technical Journal article that goes into detail but a simple comparison is good enough for most people.

Zero padding a FFT to a power of 2 is probably unnecessary if you use a modern FFT library like fftw. A library will also offer an optimized real FFT. The other advantage of not using a zero pad is that you can pick your bin widths more intelligently. It may be convenient for a user to have something like 1Hz or 5Hz or 10Hz bin widths.

The number of averages should have some reasoning as well.

Depending on your actual application, some filtering prior to your FFTs might be useful. A seismologist might be interested in frequencies below 10Hz, but a lot of other people don’t. Some degree of pre whitening is often useful.

One can have a “correct” processing chain , but nevertheless underachieve as an analysis tool.

There is a lot about how to display this information that hasn’t been touched. Real time usually means real time display.

When I started doing DSP there were a lot of tricks that you can use to save cycles. You can avoid square roots by taking the max( real, imag) - \alpha min(real, imag) where you set any negatives to positives first.

Another trick is to complex bandshift filter to use a complex fft without redundancy

  • 2
    You're right that with modern FFT libraries, power-of-2 FFTs aren't required, but if you choose a bad size (e.g. a large prime number) you can still get really bad performance. As long as your FFT size is factorable into small primes (like 2, 3, 5, 7), then you should get good speed. In some cases, you can eke out a bit more speed by padding to a power-of-2 size if you need maximum throughput. – Jason R Jun 14 at 12:06
  • Why do you recommend filtering before FFT? Linear filters are usually much easier to get right in frequency space than in time space! – leftaroundabout Jun 14 at 13:26
  • From a theoretical perspective, for a detecting a tone with bank of narrow band filters, a flat noise spectrum is prescribed. Windowing controls leakage but at a fixed level. If there is a lot of "junk" in the low frequencies that you aren't interested, like mechanical noise associated with how the sensor is mounted, you have less leakage to reject with the window, and can choose a window with a more narrow main lobe. – Stanley Pawlukiewicz Jun 14 at 13:35
  • An informal way to put is that you can do more with 2 knobs. – Stanley Pawlukiewicz Jun 14 at 14:30

Point 8. Complex numbers don't average sensibly unless you've taken steps to make them coherent from FFT to FFT. You need to transform into measures that are consistent between successive grabs.

Take the power, and average those, that's the most natural and useful. You could average the magnitude, but staying with power keeps more doors open. Making use of the noise bandwidth, finding centroids for sub-bin frequency estimation and scollop-free level estimation, these work properly with power.

You mention phase in comments. This too will vary from grab to grab if nothing is done to synchronise the source to the FFT sampling. If you have a stationary signal at multiple frequencies, then group delay will be consistent, even without synchronisation.

In addition to earlier answers regarding averaging the magnitude (or squared magnitude, or log of that) instead of each complex component, 20 Hz is a bit slow for an animation to look smooth. Try 30 or 60 Hz (use more overlap if needed for your chosen window length or FFT resolution). And sync to the display refresh rate, if possible, on your system, or else the animation rate can jitter.

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.