Search code examples
c#fftdftspectrogramspectrum

How to produce a detailed spectrogram from Fourier output?


I am developing a little application in Visual Studio 2010 in C# to draw a spectrogram (frequency "heat map").

I have already done the basic things:

  • Cut a rectangular windowed array out of the input signal array
  • Feed that array into FFT, which returns complex values
  • Store magnitude values in an array (spectrum for that window)
  • Step the window, and store the new values in other arrays, resulting in a jagged array that holds every step of windowing and their spectra
  • Draw these into a Graphics object, in color that uses the global min/max values of the heat map as relative cold and hot

The LEFT side of the screenshot shows my application, and on the RIGHT there is a spectrogram for the same input (512 samples long) and same rectangular window with size 32 from a program called "PAST - time series analysis" (https://folk.uio.no/ohammer/past/index.html). My 512 long sample array only consists of integer elements ranging from around 100 to 1400. (Note: the light-blue bar on the very right of the PAST spectrogram is only because I accidentally left an unnecessary '0' element at the end of thats input array. Otherwise they are the same.)

Link to screenshot: https://drive.google.com/open?id=1UbJ4GyqmS6zaHoYZCLN9c0JhWONlrbe3

But I have encountered a few problems here:

  1. The spectrogram seems very undetailed, related to another one that I made in "PAST time series analysis" for reference, and that one looks extremely detailed. Why is that? I know that for an e.g. 32 long time window, the FFT returns 32 elements, the 0. elem is not needed here, the next 32/2 elements have the magnitude values I need. But this means that the frequency "resolution" on the output for a 32 long window is 16. That is exactly what my program uses. But "PAST" program shows a lot more detail. If you look at the narrow lines in the blue background, you can see that they show a nice pattern in the frequency axis, but in my spectrogram that information remains unseen. Why?
  2. In the beginning (windowSize/2) wide window step-band and the ending (windowSize/2) step-band, there are less values for FFT input, thus there is less output, or just less precision. But in the "PAST" program those parts also seem relatively detailed, not just stretched bars like in mine. How can I improve that?
  3. The 0. element of the FFT return array (the so called "DC" element) is a huge number, which is a lot bigger than the sample average, or even its sum. Why is that?
  4. Why are my values (e.g. the maximum that you see near the color bar) so huge? That is just a magnitude value from the FFT output. Why are there different values in the PAST program? What correction should I use on the FFT output to get those values?

Please share your ideas, if you know more about this topic. I am very new to this. I only read first about Fourier transform a little more than a week ago.

Thanks in advance!


Solution

  • To get more smoothness in the vertical axis, zero pad your FFT so that there are more (interpolated) frequency bins in the output. For instance, zero pad your 32 data points so that you can use a 256 point or larger FFT.

    To get more smoothness in the horizontal axis, overlap your FFT input windows (75% overlap, or more).

    For both, use a smooth window function (Hamming or Von Hann, et.al.), and try wider windows, more than 32 (thus even more overlapped).

    To get better coloring, try using a color mapping table, with the input being the log() of the (non zero) magnitudes.

    You can also use multiple different FFTs per graph XY point, and decide which to color with based on local properties.