Why is my resultant signal not appearing correctly? MATLAB - matlab

I have written some code below in MATLAB to filter a Noisy signal (noise_f is the noisy signal, where it is a 1 x 256 vector):
s_nf = size(noise_f);
size_f = s_nf(2);
lp_tresh = ceil((2/3)*size_f);
lp_f = zeros(1,256);
for n = 1:lp_tresh
lp_f(n) = noise_f(n);
end
subplot(4,3,7);
plot(abs(lp_f)); title('LowPass Filter Result');
Here is a time domain image of the noisy signal:
Here is a time domain analysis of this signal:
Once I plot the result of the lowpass filter, I get this:
Now I apply the ifft on the 1 x 256 vector that represents the filtered signal and for some reason, I get this image :
Can someone explain to me how to get the proper plot of the filtered signal? All help and suggestions will be appreciated!

To get a strictly real result, the input to an IFFT must be complex conjugate symmetric. Chopping off the part of the FFT above bin N/2 (or below bin 0) destroys that symmetry if any of those bins are non-zero.
Thus, a low-pass filter will only work in the frequency domain if it's cutoff is below bin N/2 (representing Fs/2). Then make sure the filtered result is conjugate symmetric before doing the IFFT.

Related

Matlab question. What is this fft code doing?

I am new to Matlab and performing signal processing. I am trying to understand what this code is doing? How and why are we determining the indexNyquist and spectrum?
spectrum = fft(Signal,k); %generate spetrum of signal with FFT to k points
indexNyquist = round(k/2+1); %vicinity of nyquist frequency
spectrum = spectrum(1:indexNyquist); %truncate spectrum to Nyquist frequency
spectrum = spectrum/(length(Signal)); %scale spectrum by number of points
spectrum(2:end) = 2 * spectrum3(2:end); %compensate for truncating negative frequencies, but not DC component
For a purely real input signal the corresponding FFT will be complex conjugate symmetric about the Nyquist frequency, so there is no useful additional information in the top N/2 bins. We can therefore just take the bottom N/2 bins and multiply their magnitude by 2 to get a (complex) spectrum with no redundancy. This spectrum represents frequencies from 0 to Nyquist (and their aliased equivalent frequencies).
Note that bin 0 (0 Hz aka DC) is purely real and does not need to be doubled, hence the comment in your Matlab code.

FFT does not return the amplitudes in matlab?

I have generated the following time signal:
Now I want to perform a Discrete Fourier Transform by using the matlab command fft
Here is my code:
function [ xdft, omega ] = FastFourier( t, fs )
%% Inputs from other functions %%
[P_mean, x, u] = MyWay( t ) %From here comes my signal x(t)
%% FFT %%
xdft1 = fft(x); % Perform FFT
xdft2 = abs(xdft1); % Take the absolute value of the fft results
xdft = xdft2(1:length(x)/2+1); % FFT is symmetric, second half is not needed
freq = 0:fs/length(x):fs/2; % frequency axis
plot (freq(1:100),xdft(1:100));
end
And here is the plot that I get:
And what is puzzling to me is the y axis? Shouldn't the y axis represent the amplitudes of the frequency components? Is there a way to get the amplitudes of all the frequency components?
Thanks!
EDIT:
I have found that some people do the following:
n = size(x,2)/2; %The number of components and second half can be neglected again
xdft2 = abs(xdft1)/n;
This way I seem to get the amplitude spectrum, but why do I have to divide the absolute value by n?
FFT gives you a complex pair in each Frequency Bin. The first bin in the FFT is like the DC part of your signal (around 0 Hz), the second bin is Fs / N, where Fs is the sample rate and Nis the windowsize of the FFT, next bin is 2 * Fs / N and so on.
What you calc with the abs() of such a pair is the power contained in a bin.
you might also want to check this out: Understanding Matlab FFT example
Most (not all) FFT libraries preserve total energy (Parseval's theorem), which means that the magnitude has to get bigger for longer FFT windows (longer stationary waveform -> more energy). So you have to divide the result by N to get a more "natural" looking magnitude height of sinewaves in the spectrum.
If you want the amplitudes of the harmonics, then you need to plot real(xdft1) and imag(xdft1). Real(xdft1) gives you coefficients of all the cosine harmonics present in your signal, from -Fs/2 to +Fs/2, (we assume your Fs is large enough to cover all frequencies in the signal) and the imag(xdft) give the amplitudes of the sines.
What you are doing is giving you the magnitude of the signal, which is the RMS value of the total energy at a bin in both the real and imaginary frequency component.
Its often the item of most interest to people looking at a spectrum.
Basics of this: (https://www.youtube.com/watch?v=ZKNzMyS9Z6s&t=1629s)

Finding the phase from FFT on MATLAB

I know the fundamental frequency of my signal and therefore I also know the other frequencies for the harmonics, I have used the FFT command to compute the first 5 harmonics (for which I know their frequencies). Is it possible for me to find the phase with this available information?
Please note I cant be sure my signal is only one period and therefore need to calculate the phase via the known frequency values.
Code seems to be working:
L = length(te(1,:)); % Length of signal
x = te(1,:);
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(x,NFFT)/L;
f = linspace(1,5,5);
Y(1) = []; % First Value is a sum of all harmonics
figure(1);
bar(f,2*abs(Y(1:5)), 'red')
title('Transmission Error Harmonics')
xlabel('Harmonic')
ylabel('|Y(f)|')
figure(2);
bar(f,(angle(Y(1:5))))
title('Transmission Error Phase')
xlabel('Harminic')
ylabel('Angle (radians)')
Note that if your fundamental frequency is not exactly integer periodic in the fft length, then the resulting phase (atan2(xi,xr)) will be flipping signs between adjacent bins due to the discontinuity between the fft ends (or due to the rectangular window convolution), making phase interpolation interesting. So you may want to re-reference the FFT phase estimation to the center of the data window by doing an fftshift (pre, by shift/rotating elements, or post, by flipping signs in the fft result), making phase interpolation look more reasonable.
In general your Fourier transformed is complex. So if you want to know the phase of a certain frequency you calculate it with tan(ImaginaryPart(Sample)/RealPart(Sample)). This can be done by using angle().
In your case you
1- calculate fft()
2- calculate angle() for all samples of the FFT or for the samples you are interested in (i.e. the sample at your fundamental frequency/harmonic)
EDIT: an example would be
t = [0 0 0 1 0 0 0];
f = fft(t);
phase = angle(f);
phase = angle(f(3)); % If you are interested in the phase of only one frequency
EDIT2: You should not mix up a real valued spectrum [which is basically abs(fft())] with a complex fourier transformed [which is only fft()]. But as you wrote that you calculated the fft yourself I guess you have the 'original' FFT with the complex numbers.

extracting frequency of signal from FFT

I am new to Matlab and FFT.
I need to extract the dominant frequency from a signal which is varying in magnitude and frequency. I tried to perform a detrend and then an FFT to obtain the frequency but couldn't get rid of the large peak at 0Hz (DC component?). I used diff function on the signal and the resulting signal was processed through FFT. In this case, the FFT output didn't have the peak at zero. I compared the two FFT curves and it seems that except the peak at zero, the two show similar (not same) spectrum. I am wondering if diff function is a valid (and very effective) detrending method or am I losing some information here? In other words, does differentiating a signal have any effect on its frequency: [diff(sin(omega.t))= cos(omega.t) - no change in frequency]?
Thanks a lot!
By differentiating the signal you actually apply a a type of a highpass filter, a not so smart highpass which corrupts your signal. Instead you could try some other filter such as the following:
b=fir1(32,2*0.01/fs,'high');
a=1;
FilteredX=filtfilt(x,a,b)
where:
x is your original signal,
FilteredX is the filtered signal.
fs - your sample frequency.
This way you will filter out any frequencies lower then 0.01 and will almost not hurt the rest of the spectrum allowing you to detect peaks as you wished.
The discrete fourier transform X of a signal x is defined (up to scaling) by
X(k) = Sum[ exp(2*pi*i*k*n/N) * x(n) ]
If we take first differences of the signal you get
Sum[ exp(2*pi*i*k*n/N) * (x(n) - x(n-1)) ]
which you can rearrange to give
(1 - exp(2*pi*i*k/N)) * Sum[ exp(2*pi*i*k*n/N) * x(n) ]
i.e. it is a multiple of the original fourier transform. In the k = 0 case (i.e. the zero frequency component) the multiplier is zero, which explains why this removes the spike at k = 0.
Note however that the multiplier depends on the value of k, so you won't get the same signal out - you can't just take first differences to remove a spike. There is a comparison to be made with the continuous fourier transform, where if g = F(f) and h = F(df/dx) then
h(k) = i * k * g(k)
i.e. the fourier transform of the derivative is the fourier transform of the original function, multiplied by ik.

How to use inverse FFT on amplitude-frequency response?

I am trying to create an application for calculating coefficients for a graphic equalizer FIR filter. I am doing some prototyping in Matlab but I have some problems.
I have started with the following Matlab code:
% binamps vector holds 2^13 = 8192 bins of desired amplitude values for frequencies in range 0.001 .. 22050 Hz (half of samplerate 44100 Hz)
% it looks just fine, when I use Matlab plot() function
% now I get ifft
n = size(binamps,1);
iff = ifft(binamps, n);
coeffs = real(iff); % throw away the imaginary part, because FIR module will not use it anyway
But when I do the fft() of the coefficients, I see that the frequencies are stretched 2 times and the ending of my AFR data is lost:
p = fft(coeffs, n); % take the fourier transform of coefficients for a test
nUniquePts = ceil((n+1)/2);
p = p(1:nUniquePts); % select just the first half since the second half
% is a mirror image of the first
p = abs(p); % take the absolute value, or the magnitude
p = p/n; % scale by the number of points so that
% the magnitude does not depend on the length
% of the signal or on its sampling frequency
p = p.^2; % square it to get the power
sampFreq = 44100;
freqArray = (0:nUniquePts-1) * (sampFreq / n); % create the frequency array
semilogx(freqArray, 10*log10(p))
axis([10, 30000 -Inf Inf])
xlabel('Frequency (Hz)')
ylabel('Power (dB)')
So I guess, I am using ifft wrong. Do I need to make my binamps vector twice as long and create a mirror in the second part of it? If it is the case, then is it just a Matlab's implementation of ifft or also other C/C++ FFT libraries (especially Ooura FFT) need mirrored data for inverse FFT?
Is there anything else I should know to get the FIR coefficients out of ifft?
Your frequency domain vector needs to be complex rather than just real, and it needs to be symmetric about the mid point in order to get a purely real time domain signal. Set the real parts to your desired magnitude values and set the imaginary parts to zero. The real parts need to have even symmetry such that A[N - i] = A[i] (A[0] and A[N / 2] are "special", being the DC and Nyquist components - just set these to zero.)
The above applies to any general purpose complex-to-complex FFT/IFFT, not just MATLAB's implementation.
Note that if you're trying to design a time domain filter with an arbitrary frequency response then you'll need to do some windowing in the frequency domain first. You might find this article helpful - it talks about arbitrary FIR filter design usign MATLAB, in particular fir2.
To get a real result, the input to any typical generic IFFT (not just Matlab's implementation) needs to be complex-conjugate-symmetric. So doing an IFFT with a given number of independent specification points will require an FFT at least twice as long (preferably even longer to allow for some transition to zero from the highest frequency cut-off).
Trying to get a real result by throwing away the "imaginary" portion of a complex result won't work, as you will be throwing away actual required information content the time-domain filter needs for the given frequency response input to the IFFT. However, if the original data is conjugate-symmetric, then the imaginary portion of the IFFT/FFT result will be (usually insignificant) rounding-error noise that can be thrown away.
Also, the DTFT of a finite frequency response will produce an infinitely long FIR. To get a finite length FIR, you will need to compromise the specification for your frequency response specification so that there is little energy left in the latter portion of the time-domain representation that has to be truncated from the FIR to make it realizable or finite. One common (but not necessary the best) way to do this is to window the FIR result produced by the IFFT, and, by trial-and-error, try different windows until you find a FIR filter for which an FFT produces a result "close enough" to your original frequency spec.