# Why some FFT return complex array, some - mirrored real array?

I have 64 samples of a signal, two sines, one at 0.1 max freq, another at 0.5. Wrapped in gaussian: In my JS version of FFT I get an array of numbers, but the size is double (128 elements) and the second part is mirrored: But in Python, numpy's FFT returns an array of 64 complex numbers, and I like it because I can calculate magnitude and frequency!

My question: how can I convert the (kind of) mirrored FFT array of 128 real numbers to 64 complex numbers?

Here you can try this code yourself: https://stackblitz.com/edit/fft-example?file=index.ts

• How are you calculating the FFT in JS? Please share the code. You should have 128 complex numbers, OR 128 real AND 128 imaginary. Then just take half of this (these) array(s) and compute magnitude/phase just like you do with numpy's FFT
– Jdip
Commented Oct 14, 2022 at 19:08
• Here is a snippet: stackblitz.com/edit/fft-example?file=index.ts
– shal
Commented Oct 15, 2022 at 3:09

The FFT is an implementation of the Discrete Fourier Transform (DFT) which is defined as

$$X[k] = \sum_{n=0}^{N-1}x[n] e^{-j2\pi\frac{nk}{N}}$$

Both $$x[n]$$ and $$X[k]$$ are periodic with N. The DFT produces N complex outputs for N complex inputs. For real inputs the DFT has Hermitian symmetry, i.e.

$$X[-k] = X[N-k] = X^*[k]$$

where $$*$$ is the conjugate complex operator. The magnitude is symmetric and the phase is antisymmetric around $$k=0$$. This specifically implies that the vales at DC and Nyquist are real, i.e. $$X[0],X[N/2] \in \mathbb{R}$$

Some FFT implementation take of advantage of this property to save memory and computation time. The information in $$X[k]$$ in the range $$[N/2+1,N-1]$$ is redundant.

The output of a real FFT of length N is then two real numbers (DC & Nyquist) and $$N/2-1$$ complex numbers for a total of N real numbers. This can be packaged in different ways and there is no standard. Some will return a complex array of length $$N/2+1$$ some return a complex array of length $$N/2$$ with Nyquist packed into the imaginary part of the DC bin, etc.

If you don't know: READ THE DOCUMENTATION of the function you are using.

• How can my DFT input be complex? Only real, to my understanding. For example, I have audio input. Or heartbeat. How can I sample heartbeat time domain signal as complex values?
– shal
Commented Oct 15, 2022 at 14:46
• @shal Audio and heartbeat are input, but their imaginary component will be zero.
– Peter K.
Commented Oct 15, 2022 at 21:04

If you think of FFT as figuring out with correlation how much sinewave component is inside signal then by having 2 samples required for sine period we should have half frequency bins populated. FFT should return N/2 frequencies for N real input samples. So why cosine term in fft? Just sinewave matching should be enough? It turns out that something would be missing because components that did make up signal had also phase not just magnitude. Phase is extracted with second term cosine what together with sine create information about frequency AND phase. Now back to original question - are there complex input signals to fft in real world? It turns out that these are much less exotic than common sense dictates and actually employed every time you use WIFI or mobile with Quadrature modulation. Following Euler's formula for complex exponent e^ix= cos(x) +i*sin(x) quadrature baseband I (inphase,real) amplitude modulates cosine and Q (Quadrature,imaginary) modulates sinus. Also notice that by entering two components to fft (complex input both real and imaginary) you effectively have doubled bandwidth so that is why all frequencies in output not just half now have unique data.