Search code examples
fftwaveformfrequency-analysis

FFT outptut for a signal with 2 cosf() cycles


I am transforming a signal using the ZeroFFT library. The results I get from it, are not what I would intuitively expect.

As a test, I feed the FFT algorithm with a buffer that contains two full cycles of cosine:

enter image description here

Which is sampled over 512 samples.

Which are fed as int16_t values. What I expected to get back, is 256 amplitudes, with the values [ 0, 4095, 0, 0, ..., 0 ].

Instead, this is the result: 2 2052 4086 2053 0 2 2 2 1 2 2 2 4 4 3 4...

And it gets weirder! If I feed it the same signal, but shifted (so sinf() over 0 .. 4*pi instead of cosf() function) I get a completely different result: 4 10 2 16 2 4 4 4 2 2 2 3 2 4 3 4

This throws up the questions:

1. Doesn't a sine signal and cosine signal with same period, contain exactly the same frequencies?

2. If I feed it a buffer with exactly 2 cycles of cosine, wouldn't the Fourier transform result in all zeros, except for 1 frequency?

I generate my test signal as:

static void setup_reference(void)
{
  for (int i=0; i<CAPTURESZ; ++i)
  {
    const float phase = 2 * 3.14159f * i / (256.0f);
    reference_wave[i] = (int16_t) (cosf(phase) * 0x7fff);
  }
}

And call the ZeroFFT function as:

ZeroFFT(reference_Wave, CAPTURESZ);

Note: the ZeroFFT docs state that a Hanning window is applied.


Solution

  • Windowing causes some spectral leakage. Including the window function, the wave now looks like this:

    windows cosine

    If I feed it a buffer with exactly 2 cycles of cosine, wouldn't the Fourier transform result in all zeros, except for 1 frequency?

    Yes, if you do it without windowing. Actually two frequencies: both the positive frequency that you expect, and the equivalent negative frequency, though not all FFT functions will include the negative frequencies in their output (for Real input, the result is Hermitian-symmetric, there is no extra information in the negative frequencies). For practical reasons, since neither the input signal nor the FFT calculation are exact, you may not get exactly zero everywhere else either, but it should be close - that's mainly a concern for floating point output.

    By the way by this I don't mean that windowing is bad, but in this special case (perfectly periodic input) it didn't work out in your favour.

    As for the sine wave, the magnitudes of the result should be similar (within reason - exactness shouldn't be expected), but the comments on the FFT function you used mention

    The complex portion is discarded, and the real values are returned.

    While phase shifts would not change the magnitudes much, they change the phases of the results, and therefore also their Real component.