Finding the phase of each harmonics using fft - matlab

I use Matlab.
I have a sinusoidal signal :
X (amp:220/ Freq:50)
to which I add 3 harmonics :
x1 => (h2) amp:30 / Freq:100 / phase:30°
x2 => (h4) amp:10 / Freq:200 / phase:50°
x3 => (h6) amp:05 / Freq:300 / phase:90°
I sum all the signals together (like X containing 3 harmonics), the resulting signal is called : Xt
Here is the code :
%% Original signal
X = 220.*sin(2 .* pi .* 50 .* t);
%% Harmonics
x1 = 30.*sin(2 .* pi .* 100 .* t + 30);
x2 = 10.*sin(2 .* pi .* 200 .* t + 50);
x3 = 05.*sin(2 .* pi .* 300 .* t + 90);
%% adding the harmonics
Xt = X + x1 + x2 + x3;
What I want to do is : find the 3 harmonics signal (their amplitude, frequency and phase) starting for the summed signal Xt and knowing the fundamental signal X (amplitude and frequency) !
So far, I was able using fft, to retrieve the frequencies and the amplitudes of the harmonics, the problem now is finding the phases of the harmonics (in our case : 30°, 50° and 90°).

The FFT returns you an array consisting of complex numbers. To define phases of the frequency components you need to use angle() function for complex numbers. Don't forget: the phase of your harmonics has to be given in radians.
Here is the code:
Fs = 1000; % Sampling frequency
t=0 : 1/Fs : 1-1/Fs; %time
X = 220*sin(2 * pi * 50 * t);
x1 = 30*sin(2*pi*100*t + 30*(pi/180));
x2 = 10*sin(2*pi*200*t + 50*(pi/180));
x3 = 05*sin(2*pi*300*t + 90*(pi/180));
%% adding the harmonics
Xt = X + x1 + x2 + x3;
%Transformation
Y=fft(Xt); %FFT
df=Fs/length(Y); %frequency resolution
f=(0:1:length(Y)/2)*df; %frequency axis
subplot(2,1,1);
M=abs(Y)/length(Xt)*2; %amplitude spectrum
stem(f, M(1:length(f)), 'LineWidth', 0.5);
xlim([0 350]);
grid on;
xlabel('Frequency (Hz)')
ylabel('Magnitude');
subplot(2,1,2);
P=angle(Y)*180/pi; %phase spectrum (in deg.)
stem(f, P(1:length(f)), 'LineWidth', 0.5);
xlim([0 350]);
grid on;
xlabel('Frequency (Hz)');
ylabel('Phase (degree)');
It will result in such a mess (but you can see your amplitudes very well):
You can see a lot of phase components on the second plot. But if you eliminate all the frequencies which correspond to zero amplitudes, you will see your phases.
Here we are:
Y=fft(Xt); %FFT
df=Fs/length(Y); %frequency resolution
f=(0:1:length(Y)/2)*df; %frequency axis
subplot(2,1,1);
M=abs(Y)/length(Xt)*2; %amplitude spectrum
M_rounded = int16(M(1:size(f, 2))); %Limit the frequency range
ind = find(M_rounded ~= 0);
stem(f(ind), M(ind), 'LineWidth', 0.5);
xlim([0 350]);
grid on;
xlabel('Frequency (Hz)')
ylabel('Magnitude');
subplot(2,1,2);
P=angle(Y)*180/pi; %phase spectrum (in deg.)
stem(f(ind), P(ind), 'LineWidth', 0.5);
xlim([0 350]);
ylim([-100 100]);
grid on;
xlabel('Frequency (Hz)');
ylabel('Phase (degree)');
Now you can see the phases, but all of them are shifted to 90 degrees. Why? Because the FFT works with cos() instead of sin(), so:
X = 220*sin(2*pi*50*t + 0*(pi/180)) = 220*cos(2*pi*50*t - 90*(pi/180));
UPDATE
What if the parameters of some signal components are not integer numbers?
Let's add a new component x4:
x4 = 62.75*cos(2*pi*77.77*t + 57.62*(pi/180));
Using the provided code you will get the following plot:
This is not really what we expected to get, isn't it? The problem is in the resolution of the frequency samples. The code approximates the signal with harmonics, which frequencies are sampled with 1 Hz. It is obviously not enough to work with frequencies like 77.77 Hz.
The frequency resolution is equal to the inversed value of the signal's time. In our previous example the signal's length was 1 second, that's why the frequency sampling was 1/1s=1Hz. So in order to increase the resolution, you need to expand the time window of the processed signal. To do so just correct the definition of the vaiable t:
frq_res = 0.01; %desired frequency resolution
t=0 : 1/Fs : 1/frq_res-1/Fs; %time
It will result in the following spectra:
UPDATE 2
It does not matter, which frequency range has to be analyzed. The signal components can be from a very high range, what is shown in the next example. Suppose the signal looks like this:
f=20e4; % 200 KHz
Xt = sin(2*pi*(f-55)*t + pi/7) + sin(2*pi*(f-200)*t-pi/7);
Here is the resulting plot:
The phases are shifted to -90 degrees, what was explained earlier.
Here is the code:
Fs = 300e4; % Sampling frequency
frq_res = 0.1; %desired frequency resolution
t=0 : 1/Fs : 1/frq_res-1/Fs; %time
f=20e4;
Xt = sin(2*pi*(f-55)*t + pi/7) + sin(2*pi*(f-200)*t-pi/7);
Y=fft(Xt); %FFT
df=Fs/length(Y); %frequency resolution
f=(0:1:length(Y)/2)*df; %frequency axis
subplot(2,1,1);
M=abs(Y)/length(Xt)*2; %amplitude spectrum
M_rounded = int16(M(1:size(f, 2))); %Limit the frequency range
ind = find(M_rounded ~= 0);
stem(f(ind), M(ind), 'LineWidth', 0.5);
xlim([20e4-300 20e4]);
grid on;
xlabel('Frequency (Hz)')
ylabel('Magnitude');
subplot(2,1,2);
P=angle(Y)*180/pi; %phase spectrum (in deg.)
stem(f(ind), P(ind), 'LineWidth', 0.5);
xlim([20e4-300 20e4]);
ylim([-180 180]);
grid on;
xlabel('Frequency (Hz)');
ylabel('Phase (degree)');

To start off we should note (as you correctly found out in comments) that Matlab uses radians for angles, so the harmonics should be:
%% Harmonics
x1 = 30.*sin(2 .* pi .* 100 .* t + 30*pi/180);
x2 = 10.*sin(2 .* pi .* 200 .* t + 50*pi/180);
x3 = 05.*sin(2 .* pi .* 300 .* t + 90*pi/180);
The simple case
The process of estimating the amplitude, frequency and phase of the frequency components will usually start off with taking the Fast Fourier Transform (FFT), and selecting the strongest frequency components:
% Compute the frequency spectrum
N = length(Xt);
Xf = fft(Xt);
Nmax = N/2 + 1;
Xf = Xf(1:Nmax);
% Locate the peaks
largest_peak = max(20*log10(abs(Xf)));
peak_floor = largest_peak - 100; % to reject peaks from spectral leakage and noise
[pks,idx] = findpeaks((max(peak_floor, 20*log10(abs(Xf))) - peak_floor)')
Now if the fundamental frequency and the frequency of the harmonics happens to be exact multiples of fs/N where fs is the sampling rate and N is the number of samples (in this case length(Xt)) then the tones will fall exactly on a bin, and the frequencies, amplitudes and phases of each component can be estimated fairly easily with:
Amp = 2*abs(Xf(idx))/N;
freq = (idx-1)*fs/N;
phase = angle(Xf(idx));
phase = phase - phase(1); % set phase reference to that of the fundamental
The usual and more complicated reality
If on the other hand the frequency components are not exact multiples of fs/N, (or at least are not known to be exact multiples of fs/N, you are after all trying to estimate the frequency of those components) then things get more complicated. Note that this can have a particularly significant effect on the phase estimate.
We start off by recalling that a pure complex tone (exp(2*pi*j*n*f/fs)) of finite length N has a Discrete Fourier Transform (DFT) given by:
One estimation approach could be to start by estimating the frequency. The amplitude and phase can be factored out by looking at the ratio of the magnitudes of two successive bins of Xf around the peak, mainly at indices idx(i) and idx(i)+1. Under the assumption that those two bins suffer little interference, then the ratio can be expressed as:
ratio = abs(Xf(idx(i)+1)/Xf(idx))
= abs(sin(pi*frac/N)/sin(pi*(frac-1)/N))
Where the frequency to be estimated is f = (idx(i)-1 + frac)*fs/N. The parameter frac can then be obtained with the Newton-Raphson method:
% Solve for "f" for which ratio = sin(pi*frac/N)/sin(pi*(frac-1)/N)
function f = fractional_frequency(ratio, N)
niter = 20;
K = (pi/N) * sin(pi/N);
f = 0;
for i=1:niter
a = sin(pi*f/N);
b = sin(pi*(f-1)/N);
y = ratio - a/b;
yp = K / (b^2);
f = max(-0.5, min(f - y/yp, 0.5));
end
end
Which we use to estimate the frequency with:
freq = zeros(1,length(idx));
for i=1:length(idx)
ratio = abs(Xf(idx(i)+1))/abs(Xf(idx(i)));
if (abs(Xf(idx(i)+1)) > abs(Xf(idx(i)-1)))
ratio = -ratio;
end
frac = fractional_frequency(ratio, N)
freq(i) = (idx(i)-1+frac)*fs/N;
end
Now that we have the tone frequency, we can obtain the amplitude and phase by fitting the DFT equation given above (where we also add a factor of 2 for the amplitude by since we are dealing with a real tone):
Amp(i) = 2 * abs(Xf(idx(i))) * abs(sin(pi*frac/N)/sin(pi*frac));
phase(i) = angle( Xf(idx(i)) .* (1-exp(2*pi*frac*j/N)) ./ (1-exp(2*pi*frac*j)) );
And putting it all together:
Amp = zeros(1,length(idx));
freq = zeros(1,length(idx));
phase = zeros(1,length(idx));
for i=1:length(idx)
ratio = abs(Xf(idx(i)+1))/abs(Xf(idx(i)));
if (abs(Xf(idx(i)+1)) > abs(Xf(idx(i)-1)))
ratio = -ratio;
end
frac = fractional_frequency(ratio, N)
freq(i) = (idx(i)-1+frac)*fs/N;
Amp(i) = 2 * abs(Xf(idx(i))) * abs(sin(pi*frac/N)/sin(pi*frac));
phase(i) = angle( Xf(idx(i)) .* (1-exp(2*pi*frac*j/N)) ./ (1-exp(2*pi*frac*j)) );
end
phase = phase - phase(1); % set phase reference to that of the fundamental

Related

FSK modulation matlab code is not working as expected

This is my code for generating a TTL wave with frequency 30 Hz and modulate it with FSK and carrier frequency 400
f=30;
T = 1/f;
t = linspace(0, T*10, 1000);
y = (1/2)*square(t/T*2*pi)+(1/2);
plot(t, y);
hold on;
fc=400;
df=20;
y_m = cos(2.*pi.*(fc+(2.*y).*df).*t);
plot(t,y_m);
hold off;
and this is the result:
First of all, I have phase discontinuity when TTL changes from 0 to 1 or viser versa, and the second problem is that the domain of modulated signal is not the same every where and it changes...
How Can I solve these problems?
For solving the problem of discontinuities, you should make sure the condition for Continuous-Phase FSK (CPFSK) is met; that's the frequency deviation in rad/s should be an integral multiple of pi/T, which translates into 1/2T in Hz. If you choose arbitrary values for Δf, you should expect discontinuities.
For the second problem of non-constant amplitude, you should increase the number of points for the cosine calculation to be smooth enough.
clear, close
f = 30;
T = 1/f;
t = linspace(0, T*5, 10000);
y = 1/2 * square(t/T*2*pi) + 1/2;
plot(t, y, "LineWidth", 1);
hold on;
fc = 400;
df = 20;
y_m = cos(2*pi*(fc+y*df/T) .* t);
plot(t, y_m, "LineWidth", 1);
axis tight
ylim([-1.2 1.2])
hold off

MATLAB: How to apply ifft correctly to bring a "filtered" signal back to the time doamin?

I am trying to get the output of a Gaussian pulse going through a coax cable. I made a vector that represents a coax cable; I got attenuation and phase delay information online and used Euler's equation to create a complex array.
I FFTed my Gaussian vector and convoluted it with my cable. The issue is, I can't figure out how to properly iFFT the convolution. I read about iFFt in MathWorks and looked at other people's questions. Someone had a similar problem and in the answers, someone suggested to remove n = 2^nextpow2(L) and FFT over length(t) instead. I was able to get more reasonable plot from that and it made sense to why that is the case. I am confused about whether or not I should be using the symmetry option in iFFt. It is making a big difference in my plots. The main reason I added the symmetry it is because I was getting complex numbers in the iFFTed convolution (timeHF). I would truly appreciate some help, thanks!
clc, clear
Fs = 14E12; %1 sample per pico seconds
tlim = 4000E-12;
t = -tlim:1/Fs:tlim; %in pico seconds
ag = 0.5; %peak of guassian
bg = 0; %peak location
wg = 50E-12; %FWHM
x = ag.*exp(-4 .* log(2) .* (t-bg).^2 / (wg).^2); %Gauss. in terms of FWHM
Ly = x;
L = length(t);
%n = 2^nextpow2(L); %test output in time domain with and without as suggested online
fNum = fft(Ly,L);
frange = Fs/L*(0:(L/2)); %half of the spectrum
fNumMag = abs(fNum/L); %divide by n to normalize
% COAX modulation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%phase data
mu = 4*pi*1E-7;
sigma_a = 2.9*1E7;
sigma_b = 5.8*1E6;
a = 0.42E-3;
b = 1.75E-3;
er = 1.508;
vf = 0.66;
c = 3E8;
l = 1;
Lso = sqrt(mu) /(4*pi^3/2) * (1/(sqrt(sigma_a)*a) + 1/(b*sqrt(sigma_b)));
Lo = mu/(2*pi) * log(b/a);
%to = l/(vf*c);
to = 12E-9; %measured
phase = -pi*to*(frange + 1/2 * Lso/Lo * sqrt(frange));
%attenuation Data
k1 = 0.34190;
k2 = 0.00377;
len = 1;
mldb = (k1 .* sqrt(frange) + k2 .* frange) ./ 100 .* len ./1E6;
mldb1 = mldb ./ 0.3048; %original eqaution is in inch
tfMag = 10.^(mldb1./-10);
% combine to make in complex form
tfC = [];
for ii = 1: L/2 + 1
tfC(ii) = tfMag(ii) * (cosd(phase(ii)) + 1j*sind(phase(ii)));
end
%END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%convolute both h and signal
fNum = fNum(1:L/2+1);
convHF = tfC.*fNum;
convHFMag = abs(convHF/L);
timeHF = ifft(convHF, length(t), 'symmetric'); %this is the part im confused about
% Ignore,
% tfC(numel(fNum)) = 0;
% convHF = tfC.*fNum;
% convHFMag = abs(convHF/n);
% timeHF = ifft(convHF);
%% plotting
% subplot(2, 2, 1);
% plot(t, Ly)
% title('Gaussian input');
% xlabel('time in seconds')
% ylabel('V')
% grid
subplot(2, 2, 1)
plot(frange, abs(tfC(1: L/2 + 1)));
set(gca, 'Xscale', 'log')
title('coax cable model')
xlabel('Hz')
ylabel('|H(s)|V/V')
grid
ylim([0 1.1])
subplot(2, 2, 2);
plot(frange, convHFMag(1:L/2+1), '.-', frange, fNumMag(1:L/2+1)) %make both range and function the same lenght
title('The input signal Vs its convolution with coax');
xlabel('Hz')
ylabel('V')
legend('Convolution','Lorentzian in frequecuency domain');
xlim([0, 5E10])
grid
subplot(2, 2, [3, 4]);
plot(t, Ly, t, timeHF)
% plot(t, real(timeHF(1:length(t)))) %make both range and function the same lenght
legend('Input', 'Output')
title('Signal at the output')
xlabel('time in seconds')
ylabel('V')
grid
It's important to understand deeply the principles of the FFT to use it correctly.
When you apply Fourier transform to a real signal, the coefficients at negative frequencies are the conjugate of the ones at positive frequencies. When you apply FFT to a real numerical signal, you can show mathematically that the conjugates of the coefficients that should be at negative frequencies (-f) will now appear at (Fsampling-f) where Fsampling=1/dt is the sampling frequency and dt the sampling period. This behavior is called aliasing and is present when you apply fft to a discrete time signal and the sampling period should be chosen small enaough for those two spectra not to overlap Shannon criteria.
When you want to apply a frequency filter to a signal, we say that we keep the first half of the spectrum because the high frequencies (>Fsampling/2) are due to aliasing and are not characteristics of the original signal. To do so, we put zeros on the second half of the spectra before multiplying by the filter. However, by doing so you also lose half of the amplitude of the original signal that you will not recover with ifft. The option 'symmetric' enable to recover it by adding in high frequencis (>Fsampling/2) the conjugate of the coefficients at lower ones (<Fsampling/2).
I simplified the code to explain briefly what's happening and implemented for you at line 20 a hand-made symmetrisation. Note that I reduced the sampling period from one to 100 picoseconds for the spectrum to display correctly:
close all
clc, clear
Fs = 14E10; %1 sample per pico seconds % CHANGED to 100ps
tlim = 4000E-12;
t = -tlim:1/Fs:tlim; %in pico seconds
ag = 0.5; %peak of guassian
bg = 0; %peak location
wg = 50E-12; %FWHM
NT = length(t);
x_i = ag.*exp(-4 .* log(2) .* (t-bg).^2 / (wg).^2); %Gauss. in terms of FWHM
fftx_i = fft(x_i);
f = 1/(2*tlim)*(0:NT-1);
fftx_r = fftx_i;
fftx_r(floor(NT/2):end) = 0; % The removal of high frequencies due to aliasing leads to losing half the amplitude
% HER YOU APPLY FILTER
x_r1 = ifft(fftx_r); % without symmetrisation (half the amplitude lost)
x_r2 = ifft(fftx_r, 'symmetric'); % with symmetrisation
x_r3 = ifft(fftx_r+[0, conj(fftx_r(end:-1:2))]); % hand-made symmetrisation
figure();
subplot(211)
hold on
plot(t, x_i, 'r')
plot(t, x_r2, 'r-+')
plot(t, x_r3, 'r-o')
plot(t, x_r1, 'k--')
hold off
legend('Initial', 'Matlab sym', 'Hand made sym', 'No sym')
title('Time signals')
xlabel('time in seconds')
ylabel('V')
grid
subplot(212)
hold on
plot(f, abs(fft(x_i)), 'r')
plot(f, abs(fft(x_r2)), 'r-+')
plot(f, abs(fft(x_r3)), 'r-o')
plot(f, abs(fft(x_r1)), 'k--')
hold off
legend('Initial', 'Matlab sym', 'Hand made sym', 'No sym')
title('Power spectra')
xlabel('frequency in hertz')
ylabel('V')
grid
Plots the result:
Do not hesitate if you have further questions. Good luck!
---------- EDIT ----------
The amplitude of discrete Fourier transform is not the same as the continuous one. If you are interested in showing signal in frequency domain, you will need to apply a normalization based on the convention you have chosen. In general, you use the convention that the amplitude of the Fourier transform of a Dirac delta function has amplitude one everywhere.
A numerical Dirac delta function has an amplitude of one at an index and zeros elsewhere and leads to a power spectrum equal to one everywhere. However in your case, the time axis has sample period dt, the integral over time of a numerical Dirac in that case is not 1 but dt. You must normalize your frequency domain signal by multiplying it by a factor dt (=1picoseceond in your case) to respect the convention. You can also note that this makes the frequency domain signal homogeneous to [unit of the original multiplied by a time] which is the correct unit of a Fourier transform.

Scaling amplitudes by two for the FFT in MATLAB

I just read the example of Mablab tutorial, trying to studying the FFT function.
Can anyone tell me that for the final step, why P1(2:end-1) = 2*P1(2:end-1). In my opinion, it is not necessary to multiply by 2.
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sampling period
L = 1000; % Length of signal
t = (0:L-1)*T; % Time vector
%--------
S = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
%---------
X = S + 2*randn(size(t));
%---------
plot(1000*t(1:50),X(1:50))
title('Signal Corrupted with Zero-Mean Random Noise')
xlabel('t (milliseconds)')
ylabel('X(t)')
Y = fft(X);
P2 = abs(Y/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(L/2))/L;
plot(f,P1)
title('Single-Sided Amplitude Spectrum of X(t)')
xlabel('f (Hz)')
ylabel('|P1(f)|')
Y = fft(S);
P2 = abs(Y/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
plot(f,P1)
title('Single-Sided Amplitude Spectrum of S(t)')
xlabel('f (Hz)')
ylabel('|P1(f)|')
Matlab sample
The reason for the multiplication by 2 is that the spectrum returned by fft is symmetric about the DC component. Since they are showing the single-sided amplitude spectrum, the amplitude of each point is going to be doubled to account for the contributions of data on the other side of the spectrum. For example, the single-sided amplitude of pi/4 is the amplitude at pi/4 plus the amplitude at -pi/4.
The first sample is skipped since it is the DC point and therefore shared between the two sides of the spectrum.
So for example, if we look at the fft of their example signal with a 50Hz sinusoid of amplitude 0.7 and a 120Hz sinusoid of amplitude 1.
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sampling period
L = 1000; % Length of signal
t = (0:L-1)*T; % Time vector
S = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
% Compute the FFT
Y = fft(S);
% Compute the amplitudes
amplitude = abs(Y / L);
% Figure out the corresponding frequencies
f = Fs/L*[0:(L/2-1),-L/2:-1]
% Plot the result
plot(f, amplitude)
When we plot this, you'll see that it's symmetric and the original input amplitude is only realized by combining the amplitudes from both sides of the spectrum.
A slightly more explicit version of what they have done would be to be the following which sums the two halves of the spectrum
P1(2:end-1) = P1(2:end-1) + P2((L/2+2):end);
But since by definition the spectrum is symmetric, the opt to simply multiply by 2.

adding white Gaussian noise using matlab

Add white Gaussian noise to your recorded voice signal, with a " spectrum that does not
conflict with your voice spectrum" (High frequency noise).
So for the above statment, does it means their magnitude should be the same?
I have added white Gaussian on my voice using matlab command :
noisyVoice = awgn(myVoice,1)
This is the graph of both my voice and the noisy voise ( the one with added white Gaussian noise) :
One solution is to filter the Gaussian noise and then modulate it to a specific frequency band.
Fs = 1000;
L = 500;
t = (0 : L-1)/Fs;
x = chirp(t,10,.5,100);
NFFT = 2^nextpow2(L);
Y = fft(x,NFFT)/L;
f = Fs / 2 * linspace(0,1,NFFT/2+1);
subplot(211)
plot(f,2*abs(Y(1:NFFT/2+1)))
title('Amplitude Spectrum of Noise-free Signal')
xlabel('Frequency (Hz)')
b = fir2(30,[0 2*50 2*50 Fs]/Fs,[1 1 0 0]);
n = randn(L, 1);
nb = filter(b,1,n);
newx = x + nb' .* cos(2*pi*300*t); % x + modulated noise (Fc = 300Hz)
newY = fft(newx,NFFT)/L;
subplot(212)
plot(f,2*abs(newY(1:NFFT/2+1)))
title('Amplitude Spectrum of Noisy Signal')
xlabel('Frequency (Hz)')
You should adjust the low-pass filter and modulation frequency with your data.

Fourier transform and LTI filter and frequency response in Matlab

I'm new to Matlab for LTI signal processing and wondering if anyone can help with something that I'm sure is meant to be basic. I've spent hours and hours researching and obtaining background information and still cannot obtain a clear path to tackle these problems. So far, from scratch, I have generated a signal required and managed to use the fft function to produce the signal's DFT:
function x = fourier_rikki(A,t,O)
Fs = 1000;
t = 0:(1/Fs):1;
A = [0.5,0,0.5];
N = (length(A) - 1)/2;
x = zeros(size(t));
f1 = 85;
O1 = 2*pi*f1;
for k = 1:length(A)
x1 = x + A(k)*exp(1i*O1*t*(k-N-1));
end
f2 = 150;
O2 = 2*pi*f2;
for k = 1:length(A);
x2 = x + A(k)*exp(1i*O2*t*(k-N-1));
end
f3 = 330;
O3 = 2*pi*f3;
for k = 1:length(A);
x3 = x + A(k)*exp(1i*O3*t*(k-N-1));
end
signal = x1 + x2 + x3;
figure(1);
subplot(3,1,1);
plot(t, signal);
title('Signal x(t) in the Time Domain');
xlabel('Time (Seconds)');
ylabel('x(t)');
X = fft(signal); %DFT of the signal
subplot(3,1,2);
plot(t, X);
title('Power Spectrum of Discrete Fourier Transform of x(t)');
xlabel('Time (Seconds)');
ylabel('Power');
f = linspace(0, 1000, length(X)); %?
subplot(3,1,3);
plot(f, abs(X)); %Only want the positive values
title('Spectral Frequency');
xlabel('Frequency (Hz)'); ylabel('Power');
end
At this stage, I'm assuming this is correct for:
"Generate a signal with frequencies 85,150,330Hz using a sampling frequency of 1000Hz - plot 1seconds worth of the signal and its Discrete Fourier Transform."
The next step is to "Find the frequency response of an LTI system that filters out the higher and lower frequencies using the Fourier Transform". I'm stuck trying to create an LTI system that does that! I have to be left with the 150Hz signal, and I'm guessing I perform the filtering on the FFT, perhaps using conv.
My course is not a programming course - we are not assessed on our programming skills and I have minimal Matlab experience - basically we have been left to our own devices to struggle through, so any help would be greatly appreciated! I am sifting through tonnes of different examples and searching Matlab functions using 'help' etc, but since each one is different and does not have a break down of the variables used, explaining why certain parameters/values are chosen etc. it is just adding to the confusion.
Among many (many) others I have looked at:
http://www.ee.columbia.edu/~ronw/adst-spring2010/lectures/matlab/lecture1.html
http://gribblelab.org/scicomp/09_Signals_and_sampling.html section 10.4 especially.
As well as Matlab Geeks examples and Mathworks Matlab function explanations.
I guess the worst that can happen is that nobody answers and I continue burning my eyeballs out until I manage to come up with something :) Thanks in advance.
I found this bandpass filter code as a Mathworks example, which is exactly what needs to be applied to my fft signal, but I don't understand the attenuation values Ast or the amount of ripple Ap.
n = 0:159;
x = cos(pi/8*n)+cos(pi/2*n)+sin(3*pi/4*n);
d = fdesign.bandpass('Fst1,Fp1,Fp2,Fst2,Ast1,Ap,Ast2',1/4,3/8,5/8,6/8,60,1,60);
Hd = design(d,'equiripple');
y = filter(Hd,x);
freq = 0:(2*pi)/length(x):pi;
xdft = fft(x);
ydft = fft(y);
plot(freq,abs(xdft(1:length(x)/2+1)));
hold on;
plot(freq,abs(ydft(1:length(x)/2+1)),'r','linewidth',2);
legend('Original Signal','Bandpass Signal');
Here is something you can use as a reference. I think I got the gist of what you were trying to do. Let me know if you have any questions.
clear all
close all
Fs = 1000;
t = 0:(1/Fs):1;
N = length(t);
% 85, 150, and 330 Hz converted to radian frequency
w1 = 2*pi*85;
w2 = 2*pi*150;
w3 = 2*pi*330;
% amplitudes
a1 = 1;
a2 = 1.5;
a3 = .75;
% construct time-domain signals
x1 = a1*cos(w1*t);
x2 = a2*cos(w2*t);
x3 = a3*cos(w3*t);
% superposition of 85, 150, and 330 Hz component signals
x = x1 + x2 + x3;
figure
plot(t(1:100), x(1:100));
title('unfiltered time-domain signal, amplitude vs. time');
ylabel('amplitude');
xlabel('time (seconds)');
% compute discrete Fourier transform of time-domain signal
X = fft(x);
Xmag = 20*log10(abs(X)); % magnitude spectrum
Xphase = 180*unwrap(angle(X))./pi; % phase spectrum (degrees)
w = 2*pi*(0:N-1)./N; % normalized radian frequency
f = w./(2*pi)*Fs; % radian frequency to Hz
k = 1:N; % bin indices
% plot magnitude spectrum
figure
plot(f, Xmag)
title('frequency-domain signal, magnitude vs. frequency');
xlabel('frequency (Hz)');
ylabel('magnitude (dB)');
% frequency vector of the filter. attenuates undesired frequency components
% and keeps desired components.
H = 1e-3*ones(1, length(k));
H(97:223) = 1;
H((end-223):(end-97)) = 1;
% plot magnitude spectrum of signal and filter
figure
plot(k, Xmag)
hold on
plot(k, 20*log10(H), 'r')
title('frequency-domain signal (blue) and filter (red), magnitude vs. bin index');
xlabel('bin index');
ylabel('magnitude (dB)');
% filtering in frequency domain is just multiplication
Y = X.*H;
% plot magnitude spectrum of filtered signal
figure
plot(f, 20*log10(abs(Y)))
title('filtered frequency-domain signal, magnitude vs. frequency');
xlabel('frequency (Hz)');
ylabel('magnitude (dB)');
% use inverse discrete Fourier transform to obtain the filtered time-domain
% signal. This signal is complex due to imperfect symmetry in the
% frequency-domain, however the imaginary components are nearly zero.
y = ifft(Y);
% plot overlay of filtered signal and desired signal
figure
plot(t(1:100), x(1:100), 'r')
hold on
plot(t(1:100), x2(1:100), 'linewidth', 2)
plot(t(1:100), real(y(1:100)), 'g')
title('input signal (red), desired signal (blue), signal extracted via filtering (green)');
ylabel('amplitude');
xlabel('time (seconds)');
Here is the end result...