2

The DFT formula is $$X(k) = \sum x(n)e^{-i2πkn/N}$$

Is it possible to obtain absolute values from the DFT without having to calculate the imaginary components? I only need the signal amplitude values, not phase. I'm trying to create a spectrogram so I'm wondering if there's a shortcut or if I have to program complex math into the programming language

Gilles
  • 3,386
  • 3
  • 21
  • 28
user4757174
  • 155
  • 7
  • What programming language? You should generally not implement basic numerical algorithms yourself. That's an incredibly bad idea, and without wanting to be disrespectful, especially since you don't seem to have an overly deep insight in what the FFT does. – Marcus Müller Apr 23 '17 at 17:34
  • (I mean, we're happy enough to help with that :) it's just that if you want to have a fast spectrogram, use an FFT library; it's extremely unlikely you'll do any better) – Marcus Müller Apr 23 '17 at 17:54
  • 1
    The whole point of this project is to implement a simple DFT for a spectrogram. I did not mention anything about FFT nor am I trying to implement it at the moment. I am trying to use DFT and if that is computationally slow, I will look into implementing FFT algorithms. By using a library I am negating the whole point of this – user4757174 Apr 23 '17 at 18:00
  • 1
    You did mention the FFT! See your tags. But, you're contradicting yourself: if the point of the project is to write a simple DFT, you'll have to write a simple DFT, i.e. complex. If the point is however to write a simple spectrogram, you should simply use an existing FFT impl in your language! – Marcus Müller Apr 23 '17 at 18:03
  • I put it in the tags because it's related, but I wanted to see if there is a shortcut in the DFT when calculating the magnitudes, instead of calculating the complex numbers and discarding the phase. The purpose is to write a formula myself (DFT or DCT if it's more suitable) that can calculate spectrgrams. – user4757174 Apr 23 '17 at 18:11
  • So, ok, then the point is the spectrogram. What exactly are your design goals? speed? Simplicity? Maybe it would be interesting to know what you'll use the spectrogram for! – Marcus Müller Apr 23 '17 at 18:17
  • One can compute a slow simple DFT (magnitude & phase result) without any complex arithmetic. Or if you just need the DFT magnitudes, N Goertzel filters would also work. – hotpaw2 Apr 23 '17 at 18:19
  • 1
    @hotpaw2 indeed, as your answer explains very nicely! Point is that it's not any easier than the complex arithmetic. – Marcus Müller Apr 23 '17 at 18:23
  • Ia strictly real arithmetic DFT is a tons easier to explain to a student who's had some trig, but no complex numbers. Also when using vintage programming languages that don't support any complex data types (AppleSoft Basic, etc.) – hotpaw2 Apr 23 '17 at 18:33
  • 1
    I already created this program in MATLAB, I just want to recreate it in another language, this time implementing it myself instead of relying on matlab's built in functions. The program just spits out a 2d array, which is the image of the spectrogram. Speed isn't too much of a concern unless it is excessively slow – user4757174 Apr 23 '17 at 19:42
  • @user4757174 well, "excessively slow" is kind of a relative term, and assuming you don't want to take transforms that are 100s of thousands of elements long: your PC will do that, yes. Now, what I say is purely personal preference, but: assuming you're doing this in some language that has structural types (like C's struct, or python objects or...), I'd go and implement a complex type (unless your language already has one (UYLAHO)), a complex exp (UYLAHO), and a matrix-vector multiplication (UYLAHO) and just define the DFT matrix of the desired size. Now, I'm curious: which language? – Marcus Müller Apr 23 '17 at 19:55
  • I was thinking PHP or python – user4757174 Apr 24 '17 at 01:25
  • I'd recommend Python. It comes with a complex type! Also, if you need a test case for your self-written algorithms, you can test them against library implementations, which is super handy! A lot of the non-performance-critical DSP I do happens in Python. Basically, everything that doesn't happen in C/C++ or SIMD pseudo assembler. – Marcus Müller Apr 24 '17 at 08:22

2 Answers2

2

Yes. You can do the calculation. But, no, it's not a shortcut.

If you want to obtain your DFT magnitudes fast (e.g. using the O(NlogN) FFT algorithm), then you will need the complex math (or its computational equivalent). This is because the cosine and sine forms of the DFT basis vectors are orthogonal, and you need both to completely be able to represent arbitrary input waveforms. The sine portions of the basis vectors are represented by the imaginary components of an FFT's complex result. So the full complex result of an FFT needs to be computed to end up with enough information for a magnitude or amplitude result.

If a slow DFT computation is acceptable, then you could just compute the cosine components using strictly real arithmetic and then separately compute the sine components also using reals. Then compute the hypotenuse of the real triangle for the amplitude. No complex numbers needed. But this method is O(N^2), which would take a lot longer.

For just magnitude results (computed slowly), N Goertzel filters is another possibility, and may save in trig function calls.

hotpaw2
  • 35,346
  • 9
  • 47
  • 90
  • What about discrete cosine transform? Would that be a better option, in terms of computation speed, since it is only real output and I'm making a spectrogram of amplitudes? Or is it still just as slow? – user4757174 Apr 23 '17 at 17:29
  • … you could also just return a vector of zeros, that would, for a bounded input, have a bounded error, and be incredibly fast. What is appropriate depends on the data you have, and what exactly you need, and under which constraints. – Marcus Müller Apr 23 '17 at 17:35
  • There are already other answers here regarding using a DCT for spectrograms. See: https://dsp.stackexchange.com/questions/93/could-a-dct-be-used-for-an-audio-magnitude-spectrum-rather-than-dft , https://dsp.stackexchange.com/questions/28583/why-is-the-dft-used-for-spectrograms-rather-than-the-dct – hotpaw2 Apr 23 '17 at 17:42
  • Hey there, I have implemented the FFT algorithm without using complex math by calculating the real and im components separately like you said, but I used cooley tukey algorithm so its NlogN not N^2. I essentially made a 2xN array where X[N][0] is the real component and X[N][1] is the imaginary component. So to add to your answer, yes, you can do the calculation without imaginary numbers even with the NlogN algorithm – user4757174 May 13 '17 at 18:35
2

Being orthogonal, and although fast algorithms exist, Fourier techniques ultimately resorts to least-squares spectral analysis, i.e. finding a sum of terms in the shape of

$$ a_k \cos(\cdot) + b_k \sin(\cdot) $$

which can be solved by linear algebra, with pure real computations. Just remember that, at the time of Fourier (1768-1830), complex arithmetic was not fully developed. Carl F. Gauss (1777-1855) is sometimes credited of the first uses of fast techniques to solve it.

So yes, you can avoid complex numbers, but $ a \cos(\phi) + b \sin(\phi) $, being real with $a$, $b$, $\phi$ reals, is just completely equivalent to some complex number. And complex numbers are just fundamental to the analysis of linear time-invariant systems, because they form their invariant eigenvectors, or allow to diagonalize them.

user4757174
  • 155
  • 7
Laurent Duval
  • 31,850
  • 3
  • 33
  • 101