Search code examples
matlabscipysignal-processingspectrogram

matlab spectrum returns more FRAME than expected


I'm using the following code to get specgram2D from np array:

specgram2D, freq, time = mlab.specgram(samples, Fs=11025, NFFT=1024, window=mlab.window_hanning, noverlap=int(1024 * 0.5))

Then I print out specgram2D like

print len(specgram2D)  # returns 513

I got 513 instead of expected 512 which is half the window size.

What am I doing wrong?

Can I just ignore specgram2D[512]?


Solution

  • I got 513 instead of expected 512 which is half the window size.

    What am I doing wrong?

    For a real-valued signal, the frequency spectrum obtained from the Discrete Fourier Transform (DFT) is symmetric and hence only half of the spectrum is necessary to describe the entire spectrum (since the other half can be obtained from symmetry). That is probably why you are expecting the size to be exactly half the input window size of 1024.

    The problem is that with even sized inputs, the midpoint of the spectrum falls exactly on a frequency bin. As a result, that frequency bin is its own symmetry. To illustrate this, the symmetry can be seen from the following graph:

    frequency:  0   fs/N  ...       fs/2     ...       fs
    bin number: 0    1    ...   511 512  513 ... 1023 1024
                ^    ^           ^  ^ ^   ^       ^    ^
                |    |           |  |-|   |       |    |
                |    |           |        |       |    |
                |    |           |--------|       |    |
                |    |                            |    |
                |    |----------------------------|    |
                |                                      |
                |--------------------------------------|
    

    Where N is the size of the FFT (as determined by the NFFT=1024 parameter) and fs is the sampling frequency. As you can see the spectrum is fully specified by taking bins 0 to 512, inclusive. Correspondingly you should be expecting the size to be floor(N/2)+1 (simply N/2 + 1 with integer division, but I included the floor to emphasis the round down operation), or 513 in your case.

    Can I just ignore specgram2D[512]?

    As previously shown it is an integral part of the spectrum, but many applications do not specifically require every single frequency bins (i.e. ignoring that bin depends on whether your application is mostly interested in other frequency components).