0
$\begingroup$

I dont understand why my modified fft of a audio signal returns complex values after ifft. I modified my signal by zeroing out all the unnecessary freq.

FFT: Fast fourier transfrom

IFFT: Inverse fast fourier transform

Heres the matlab code and graph


[a,fs]=audioread("Recording.m4a") 

plot(a)

n=numel(a)/2  *//*since audio signal is stereo but i want only mono*

b=abs(fft(a))

y=fft(a)

c=y(:,1)     *//*to convert audio signal from stereo to mono*

plot(f,abs(c))

xlim([0 1000])


c(abs(c)<31)=0

c(round(n*1000/fs):end)=0

f=0:n-1

f=(f*fs/n)'

plot(f,abs(c))

xlim([0 1000])


z=ifft(c)

plot(z)

Original audio signal Final audio signal obtain FFT of original audio signal FFT of noise reduced audio signal

$\endgroup$
  • $\begingroup$ Fig1: Original Audio Signal Fig2: Output audio signal after performing IFFT Fig3: FFT of original audio signal Fig4: FFT of cleaned audio signal $\endgroup$ – Lelouche Lamperouge Apr 4 at 11:03
2
$\begingroup$

The short answer is do not null out the "mirror frequencies" that are located above $f_s/2$ that match the frequencies you want to keep. If your FFT was generated from a real signal, then when you do the IFFT you will get the real signal back as long as you did not zero out those upper frequencies (as you did).

The DFT (which the FFT computes) returns complex values but for real signals the “positive” frequency values will be the complex conjugate of the negative frequency values which together represent real signals. Due to how the FFT is computed, instead of returning the positive and negative frequencies from $-f_s/2$ to $+f_s/2$, instead those same frequencies are given from $0$ to $f_s$.

Consider Euler’s Identity:

$$2cos(\omega t) = e^{j\omega t}+ e^{-j\omega t}$$

If it wasn’t already clear, the general form of $Ae^{j\theta}$ represents the magnitude and phase of a complex number as $A\angle{\theta}$ so above we see how the cosine is represented by two phasors each rotating in time in opposite directions (a positive and negative frequency) such that their sum is always on the real axis.

The FFT returns the frequency bins from 0 to one sample less than the sampling frequency: $n =0$ to $N-1$ bins where each bin is spaced by $f_s/N$ with $f_s$ as the sampling rate. Due to the cyclical nature of the FFT this represents the positive and negative frequencies by mapping everything above $f_s/2$ to the negative frequencies, specifically samples $N/2 + n$ for $n\ge N/2$ map to $-N/2+n$. The command fftshift in MATLAB or Octave does this specifically.

For this reason you should NOT null out all the "mirror" frequencies that are located above $N/2$ as without them your signal will be complex. Consider the example above with the cosine.

$$2cos(2\omega_n t) = e^{j2\omega_n t}+ e^{-j2\omega_n t}$$

If sampled such that there were 100 total bins, and $\omega_n$ was the spacing on one DFT bin, then the DFT would have non zero values at the 3rd bin (bin 0 is DC) and the 2nd to last DFT bin which after shifting would be at the expected +/-2 bins. If you removed the higher bin then the resulting waveform would simply be:

$$e^{j2\omega_n t}$$

enter image description here

| improve this answer | |
$\endgroup$
  • $\begingroup$ soo how do i fix this $\endgroup$ – Lelouche Lamperouge Apr 4 at 11:34
  • $\begingroup$ Don't null out the "higher frequencies" since those are the negative frequencies you need for it to be real. I will add that explanation. $\endgroup$ – Dan Boschen Apr 4 at 11:35
1
$\begingroup$

For a real signal, the FFT is symmetric complex numbers in general. That is $X[((-k))_N] = X[((k))_N]$. When you did this

c(round(n*1000/fs):end)=0

you have disturbed the symmetry and hence, the ifft of this new signal will no longer be real. See a simple example

>> x=[1 3 5 6];
>> y=fft(x);
>> y(1:2)=0;
>> ifft(y)

ans =

  -1.7500 - 0.7500i   0.0000 + 1.0000i   0.2500 + 0.7500i   1.5000 - 1.0000i

The output is no longer real because I just set first 2 samples to 0 there by disturbing symmetry in FFT. The original FFT (its periodic extension) is symmetric as below. That is $y[((1))_4] = y[3] = y[((-1))_4]$.

>> fft(x)

ans =

  15.0000 + 0.0000i  -4.0000 + 3.0000i  -3.0000 + 0.0000i  -4.0000 - 3.0000i
| improve this answer | |
$\endgroup$
1
$\begingroup$

If you want a strictly real result from an IFFT, then you have to force the input to be conjugate symmetric. That way, all the imaginary components will cancel out to (almost) zero (except for rounding “errors” or microscopic numerical noise).

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.