soul-lang / SOUL

The SOUL programming language and API
Other
1.71k stars 96 forks source link

soul::DFT::forward output is half as long as it should be #61

Closed MichelVazirani closed 3 years ago

MichelVazirani commented 3 years ago

Hi!

I think there is an issue with the soul::DFT::forward function in soul_library_frequency.soul. Normally DFT is supposed to create two arrays of length N, one for the real component and one for the imaginary component, where N is the number of samples. This gives us N frequency bins.

In the soul::DFT::forward, you are taking the results from soul::DFT::performComplex, which are two arrays of length N as I described earlier, and you are copying half of each of them into the outputData array, which is also length N. This means you are getting rid of half of the frequency bins.

I could fix this problem myself as a pull request, but I wanted to first raise it as an issue to get your opinion and make sure this actually is a problem. If I am just making a mistake, please let me know.

Thanks so much!

cesaref commented 3 years ago

Hi,

The output is correct as it is. The reason for this is that for a real DFT with, say, 32 input samples, the output will be 17 complex numbers (if you think about it, the input cannot have information above nyquist, so we have a maximum of N/2 frequency components, but we also have the 0 'dc' frequency to consider).

Now the DC component will only have a real component, and the nyquist will only have an imaginary component, so although you have 17 output complex numbers, there are 32 degrees of freedom (2 values are 0). This makes sense, in that the frequency domain representation of the time domain signal is reversible and lossless.

The complex DFT of 32 input complex numbers generates 32 output complex numbers. Because the implementation is done in the complex domain, it is taking the above 32 input real numbers, and converting them to 32 complex numbers by putting zeros in the imaginary components, transforming this (which will generate 32 output complex numbers) but then discarding the duplicate information to generate the required output values. The complex DFT of a complex signal with zero imaginary components will have symmetrical output with the higher 16 values being a duplicate of the lower 16 values (but reversed).

I believe the implementation is correct. There's an overview of the real and complex DFT here which has a handy picture which may help my attempt at describing this in words: http://www.dspguide.com/ch12/1.htm

MichelVazirani commented 3 years ago

Hello!

Thank you so much for the explanation! You're absolutely right, it makes no sense to consider frequencies above the Nyquist. Thank you for taking the time to explain it so well!