I am trying to implement a basic DFT algorithm on Matlab.
I simply use in phase and quadrature components of a sine wave with phase modulation(increasing frequency a.k.a chirp). I do compare my results with fft command of Matlab. My code gives the same results whenever there is no phase modulation(pure sine). Whenever I add chirp modulation, results differ. For example, when I use a chirp with some bandwidth around a carrier, the expected results should be a frequency distribution of chirp bandwidth starting from carrier frequency. However, I get a copy of that result backwards starting from carrier frequency as well. You can use my code below without modifying anything. Figure 5 is my result and figure 6 is the expected result. Carrier is 256 Hz with a 10Hz bandwidth of chirp. You can see the code below. The important part is for loop where I take dft of my signal. Also uou can see my dft result below.
close all;
clear all;
%% signal generation
t = (0:0.0001:1); % 1 second window
f = 256; %freq of input signal in hertz
bw = 10; % bandwidth sweep of signal
phaseInput = 2*pi*t*bw.*t;
signalInput = sin(2*pi*f*t + phaseInput); %input signal
inphase = sin(2*pi*f*t).*cos(phaseInput); %inphase component
quadrature = cos(2*pi*f*t).*sin(phaseInput); %quadrature component
figure
plot(t,signalInput,'b',t,inphase,'g',t,quadrature,'r');
title('Input Signal');
xlabel('Time in seconds');
ylabel('Amplitude');
%% sampling signal previously generated
Fs = 1024; %sampling freq
Ts = (0:1/Fs:1);%sample times for 1 second window
sPhase = 2*pi*Ts*bw.*Ts;
sI = sin(2*pi*f*Ts).*cos(sPhase);
sQ = cos(2*pi*f*Ts).*sin(sPhase);
hold on;
plot(Ts,sI+sQ,'b*',Ts,sI,'g*',Ts,sQ,'r*');
fftSize = Fs; %Using all samples in dft
sampleIdx = (0:1:fftSize-1)';
sampledI = sI(1:fftSize)';
sampledQ = sQ(1:fftSize)';
figure;
plot(sampleIdx,sampledI,sampleIdx,sampledQ);
title('Sampled IQ Components');
%% DFT Calculation
dftI = zeros(fftSize,1);
dftQ = zeros(fftSize,1);
for w = 0:fftSize-1
%exp(-2*pi*w*t) = cos(2*pi*w*t) - i*sin(2*pi*w*t)
cI = cos(2*pi*w*sampleIdx/fftSize); %correlation cos
cQ = -sin(2*pi*w*sampleIdx/fftSize); %correlation sin
dftI(w+1) = sum(sampledI.*cI - sampledQ.*cQ); %
dftQ(w+1) = sum(sampledI.*cQ + sampledQ.*cI);
end;
figure;
plot(Fs*sampleIdx/fftSize,dftI);
title('DFT Inphase');
xlabel('Hertz');
figure
plot(Fs*sampleIdx/fftSize,dftQ);
title('DFT Quadrature');
xlabel('Hertz');
figure;
plot(Fs*sampleIdx/fftSize,sqrt(dftQ.^2+dftI.^2));
%% For comparison
sampledInput = sin(2*pi*f*Ts + sPhase);
Y = fft(sampledInput(1:1024),1024);
Pyy = Y.*conj(Y)/1024;
f = (0:1023);
figure;
plot(f,Pyy)
title('Power spectral density')
xlabel('Frequency (Hz)')
the reason lies in the fact that two different signals will definitely give your two different frequency spectrums. check out the code below, you will find that the input of the dft algorithm you actually gave is sampledI+jsampledQ. as a result, what you are doing here is NOT merely decomposing your original signal into In-phase and quadrature components, instead, you are doing Hilbert transform here -- to change a real signal into a complex one.
cI = cos(2*pi*w*sampleIdx/fftSize); %correlation cos
cQ = -sin(2*pi*w*sampleIdx/fftSize); %correlation sin
dftI(w+1) = sum(sampledI.*cI - sampledQ.*cQ); %
dftQ(w+1) = sum(sampledI.*cQ + sampledQ.*cI);
so the sampledInput for comparison should be sampledInput = sI+1i*sQ;.
Related
I have a matlab code to Frequency modulation and demodulation a signal. My code is work well for modulation part. My message signal is m and modulated signal is u, code plot the message signal and its integral in one graph for plotting 1.
Then signal modulated with carrier and program plots the modulated signal in time domain for plotting 2.
After that, by the help of some code blocks program find the frequency spectrum of modulated signal and message signal to plot graph of them for plotting 3.
In demodulation part program make some fundamental calculation for FM detection, then to obtain message signal it uses filter.
Last part program plots the graph of recovered signal with message signal to compare them.
I summarized all code because ı do not know whre is the problem.
My problem about plotting 3 when I make zoom graph 3 I see some phase foldings or like it.Graph is not symmetric according to y-axis.
I did not solve this problem, I research about them and I decided to use unwrap(). Although I tried a lot, I could not be successful. How can I get rid of this phase folding with unwrap() function. Thank you.
My matlab code is ;
ts = 0.0001;% Sampling interval
t0 = 0.15; % Duration
t = 0:ts:t0;% define time vector
%% OTHER PARAMETERS
fc = 200; % Carrier signal frequency
kf =50; % Frequency deviation constant
fs = 1/ts; % Sampling frequency
%% MESSAGE SIGNAL SIMPLY
m = 1*(t<t0/3)-2*(t<2*t0/3).*(t>=t0/3);
%% Integration of m
int_m(1) = 0;
for k =1:length(m)-1
int_m(k+1) = int_m(k) + m(k)*ts;
end
%% PLOTTING 1
figure; subplot(211); % Message signal
plot(t,m);grid on;xlabel('time');ylabel('Amplitude');
title('m(t)');ylim([-3 2]);
subplot(212);plot(t,int_m);% Integral of message signal
grid on; xlabel('time');ylabel('Amplitude');title('integral of m(t)');
ylim([-0.07 0.07]);
%% FM MODULATED SIGNAL
u = cos(2*pi*fc*t + 2*pi*kf*int_m);
%% PLOTTING 2
figure; plot(t,u); % Modulated signal in time domain
grid on;xlabel('time');
ylabel('Amplitude');title('FM :u(t)');
ylim([-1.2 1.2]);
%% FINDING FREQUENCY SPECTRUM AND PLOTTING 3
% Frequency spectrum of m(t)
f=linspace(-1/(2*ts),1/(2*ts),length(t));
M=fftshift(fft(m))./length(t); % Taking fourier transform for m(t)
U=fftshift(fft(u))./length(t); % Taking fourier transform for u(t)
figure;subplot(211); % Frequence spectrum of m(t)
plot(f,abs(M)); grid;
xlabel('Frequency in Hz');xlim([-500 500]);
ylabel('Amplitude');title('Double sided Magnitude spectrum of m(t)');
subplot(212);plot(f,abs(U)); % Frequency spectrum of u(t)
grid;xlabel('Frequency in Hz');xlim([-500 500]);
ylabel('Amplitude');title('Double sided Magnitude spectrum of u(t)');
%% DEMODULATION (Using Differentiator)
dem = diff(u);
dem = [0,dem];
rect_dem = abs(dem);
%% Filtering out High Frequencies
N = 80; % Order of Filter
Wn = 1.e-2; % Pass Band Edge Frequency.
a = fir1(N,Wn);% Return Numerator of Low Pass FIR filter
b = 1; % Denominator of Low Pass FIR Filter
rec = filter(a,b,rect_dem);
%% Finding frequency Response of Signals
fl = length(t);
fl = 2^ceil(log2(fl));
f = (-fl/2:fl/2-1)/(fl*1.e-4);
mF = fftshift(fft(m,fl)); % Frequency Response of Message Signal
fmF = fftshift(fft(u,fl)); % Frequency Response of FM Signal
rect_demF = fftshift(fft(rect_dem,fl));% Frequency Response of Rectified FM Signal
recF = fftshift(fft(rec,fl)); % Frequency Response of Recovered Message Signal
%% PLOTTING 4
figure;subplot(211);plot(t,m);grid on;
xlabel('time');ylabel('Amplitude');
title('m(t)');ylim([-3 2]);
subplot(212);plot(t,rec);
title('Recovered Signal');xlabel('{\it t} (sec)');
ylabel('m(t)');grid;
My problem is in this third graph to show well I put big picture
k = -(length(X)-1)/2:1:length(X)/2;
Your k is not symmetric.
If you work with symmetric k is it working fine?
I have some beginner, basic Physionet data I am trying to apply FFT to, but I'm a bit confused by the results I'm getting and don't think they're correct. I'm mostly using code from this example and from the fftshift documentation page with some tweaks but I'm not too sure what's wrong with my code or results. I have attached my code and snapshots of the results I'm getting.
load aami3am.mat
Fs = 720; % Sampling frequency
T = 1/Fs; % Sample time
L = 60000; % Length of signal
t = (0:L-1)*T; % Time vector
plot(t(1:43081),val(1:43081))
title('aami4b_h Signal')
xlabel('Seconds')
ylabel('ECG Amplitude')
NFFT = 2^nextpow2(L);
val = detrend(val);
Y = fft(val,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
plot(f,2*abs(Y(1:NFFT/2+1)))
title('FFT')
yY = fftshift(Y);
fshift = (-L/2:L/2-1)*(Fs/L);
powershift = abs(yY).^2/L;
plot(fshift(1:L),powershift(1:L))
title('FFT Shifted')
I'm using 43081 because there are 43081 values in the .mat file over the 60 seconds of data.
I am using the following code to generate a fft and mathematical Fourier transform of a signal. I want to then mathematically recreate the original signal of the fft. This works on the mathematical signal but not on the fft since it is a Discrete Transform. Does anyone know what change I can make to my inverse transform equation that will make it work for fft?
clear all; clc;
N = 1024;
N2 = 1023;
SNR = -10;
fs = 1024;
Ts = 1/fs;
t = (0:(N-1))*Ts;
x = 0.5*sawtooth(2*2*pi*t);
x1 = fft(x);
Magnitude1 = abs(x1);
Phase1 = angle(x1)*360/(2*pi);
for m = 1:1024
f(m) = m; % Sinusoidal frequencies
a = (2/N)*sum(x.*cos(2*pi*f(m)*t)); % Cosine coeff.
b = (2/N)*sum(x.*sin(2*pi*f(m)*t)); % Sine coeff
Magnitude(m) = sqrt(a^2 + b^2); % Magnitude spectrum
Phase(m) = -atan2(b,a); % Phase spectrum
end
subplot(2,1,1);
plot(f,Magnitude1./512); % Plot magnitude spectrum
......Labels and title.......
subplot(2,1,2);
plot(f,Magnitude,'k'); % Plot phase spectrum
ylabel('Phase (deg)','FontSize',14);
pause();
x2 = zeros(1,1024); % Waveform vector
for m = 1:24
f(m) = m; % Sinusoidal frequencies
x2 = (1/m)*(x2 + Magnitude1(m)*cos(2*pi*f(m)*t + Phase1(m)));
end
x3 = zeros(1,1024); % Waveform vector
for m = 1:24
f(m) = m; % Sinusoidal frequencies
x3 = (x3 + Magnitude(m)*cos(2*pi*f(m)*t + Phase(m)));
end
plot(t,x,'--k'); hold on;
plot(t,x2,'k');
plot(t,x3,'b');```
There are a few comments about the Fourier Transform, and I hope I can explain everything for you. Also, I don't know what you mean by "Mathematical Fourier transform", as none of the expressions in your code is resembles the Fourier series of the sawtooth wave.
To understand exactly what the fft function does, we can do things step by step.
First, following your code, we create and plot one period of the sawtooth wave.
n = 1024;
fs = 1024;
dt = 1/fs;
t = (0:(n-1))*dt;
x = 0.5*sawtooth(2*pi*t);
figure; plot(t,x); xlabel('t [s]'); ylabel('x');
We can now calculate a few things.
First, the Nyquist frequency, the maximum detectable frequency from the samples.
f_max = 0.5*fs
f_max =
512
Also, the minimum detectable frequency,
f_min = 1/t(end)
f_min =
1.000977517106549
Calculate now the discrete Fourier transform with MATLAB function:
X = fft(x)/n;
This function obtains the complex coefficients of each term of the discrete Fourier transform. Notice it calculates the coefficients using the exp notation, not in terms of sines and cosines. The division by n is to guarantee that the first coefficient is equal to the arithmetic mean of the samples
If you want to plot the magnitude/phase of the transformed signal, you can type:
f = linspace(f_min,f_max,n/2); % frequency vector
a0 = X(1); % constant amplitude
X(1)=[]; % we don't have to plot the first component, as it is the constant amplitude term
XP = X(1:n/2); % we get only the first half of the array, as the second half is the reflection along the y-axis
figure
subplot(2,1,1)
plot(f,abs(XP)); ylabel('Amplitude');
subplot(2,1,2)
plot(f,angle(XP)); ylabel('Phase');
xlabel('Frequency [Hz]')
What does this plot means? It shows in a figure the amplitude and phase of the complex coefficients of the terms in the Fourier series that represent the original signal (the sawtooth wave). You can use this coefficients to obtain the signal approximation in terms of a (truncated) Fourier series. Of course, to do that, we need the whole transform (not only the first half, as it is usual to plot it).
X = fft(x)/n;
amplitude = abs(X);
phase = angle(X);
f = fs*[(0:(n/2)-1)/n (-n/2:-1)/n]; % frequency vector with all components
% we calculate the value of x for each time step
for j=1:n
x_approx(j) = 0;
for k=1:n % summation done using a for
x_approx(j) = x_approx(j)+X(k)*exp(2*pi*1i/n*(j-1)*(k-1));
end
x_approx(j) = x_approx(j);
end
Notice: The code above is for clarification and does not intend to be well coded. The summation can be done in MATLAB in a much better way than using a for loop, and some warnings will pop up in the code, warning the user to preallocate each variable for speed.
The above code calculates the x(ti) for each time ti, using the terms of the truncated Fourier series. If we plot both the original signal and the approximated one, we get:
figure
plot(t,x,t,x_approx)
legend('original signal','signal from fft','location','best')
The original signal and the approximated one are nearly equal. As a matter of fact,
norm(x-x_approx)
ans =
1.997566360514140e-12
Is almost zero, but not exactly zero.
Also, the plot above will issue a warning, due to the use of complex coefficients when calculating the approximated signal:
Warning: Imaginary parts of complex X and/or Y arguments ignored
But you can check that the imaginary term is very close to zero. It is not exactly zero due to roundoff errors in the computations.
norm(imag(x_approx))
ans =
1.402648396024229e-12
Notice in the codes above how to interpret and use the results from the fft function and how they are represented in the exp form, not on terms of sines and cosines, as you coded.
I’m trying to implement a 32 point FFT - Equalizer - iFFT
On a step by step basis. I input a Time domain signal to a FFT block and then used iFFT to obtain the original data back.
Naturally after FFT, I get 32 points of symmetrical real and imaginary data.
I tried,
Step 1:
fft_sig = fft(data_processing_block); %FFT of the signal
ifft_sig = ifft(fft_sig); %iFFT of the signal
The output matches the input. Works like a charm.
Step 2:
fft_sig = fft(data_processing_block); %FFT of the signal
after_eq_re = real(fft_sig);
after_eq_im = imag(fft_sig);
after_eq = after_eq_re + (i*after_eq_im);
ifft_sig = ifft(after_eq); %iFFT of the signal
This also works just fine.
Step 3:
fft_sig = fft(data_processing_block); %FFT of the signal
after_eq_re = real(fft_sig).*1.0; % Multiply Real data with a constant
after_eq_im = imag(fft_sig).*1.0; % Multiply Imag data with a constant
after_eq = after_eq_re + (i*after_eq_im);
ifft_sig = ifft(after_eq); %iFFT of the signal
This also works fine.
Step 4:
I replaced the constant (1.0) with an Equalizer table. Of size 32.
Eq_data_32 =[0.0;0.1347;0.2117;0.2956;0.4146;0.5300;0.5615;0.5195;0.4391;0.3621;0.2816;0.1977;0.1837;0.1172;0.0857;0.0577;0.0;0.0577;0.0857;0.1172;0.1837;0.1977;0.2816;0.3621;0.4391;0.5195;0.5615;0.5300;0.4146;0.2956;0.2117;0.1347];
Eq_data_32(1) and Eq_data_32(17) are zeros. Eq_data_32(2:16) is symmetrical to Eq_data_32(18:32).
re_Eq_data_32 = Eq_data_32; % Equalizer data for real values
im_Eq_data_32 = -(re_Eq_data_32); % Equalizer data for imaginary values
fft_sig = fft(data_processing_block); %FFT of the signal
after_eq_re = real(fft_sig).*re_Eq_data_32';
after_eq_im = imag(fft_sig).*im_Eq_data_32';
after_eq = after_eq_re + (i*after_eq_im);
ifft_sig = ifft(after_eq); %iFFT of the signal
Now the output is distorted and does not sound good. I think this is due to symmetry of the Equalizer table. I can’t figure how to arrange the Equalizer table to preserve the symmetry. As far as I can tell, my real and imaginary Equalizer table are symmetric. So why can’t I get a clear output ?
Complete code:
Fs = 16000; % sampling frequency
no_samples = 640; % no of samples
Freq1 = 1000; % Frequency 1 of the signal
Freq2 = 2500; % Frequency 2 of the signal
Freq3 = 3500; % Frequency 3 of the signal
Amp = 0.1;
t = 1/Fs*((1:no_samples)-1); % time duration, t = 1/Fs
Input_sig_16k = Amp*sin(2*pi*Freq1*t)+Amp*sin(2*pi*Freq2*t)+Amp*sin(2*pi*Freq3*t); % Multitone Input Signal
% Equlizer data
Eq_data_32 =[0.0;0.1347;0.2117;0.2956;0.4146;0.5300;0.5615;0.5195;0.4391;0.3621;0.2816;0.1977;0.1837;0.1172;0.0857;0.0577;0.0;0.0577;0.0857;0.1172;0.1837;0.1977;0.2816;0.3621;0.4391;0.5195;0.5615;0.5300;0.4146;0.2956;0.2117;0.1347];
re_Eq_data_32 = Eq_data_32; % Equalizer data for real values
im_Eq_data_32 = -(re_Eq_data_32);
window_size = 32;
for ii = 1:(length(Input_sig_16k)/window_size)-1
data_range = (((ii-1)*window_size)+1:((ii-1)*window_size)+32);
data_block = Input_sig_16k(data_range);
fft_sig = fft(data_block); %FFT of the signal
after_eq_re = real(fft_sig).*re_Eq_data_32'; % Multiply real portion of FFT with Equalizer
after_eq_im = imag(fft_sig).*im_Eq_data_32'; % Mutliply imaginary portion with Equalizer
after_eq = after_eq_re + (i*after_eq_im);
ifft_sig = ifft(fft_sig); %iFFT of the signal
data_full(data_range) = ifft_sig; % Output signal
end
plot(Input_sig_16k,'-og'), grid on; % plot and compare both the signals
hold on;
plot(data_full,'-xr')
hold off;
Multiplication in the frequency domain is circular convolution in the time domain. Circular convolution means that the end of your multiplication filtering process wraps around and corrupts the beginning of each FFT/IFFT buffer.
Instead, zero-pad each FFT by at least the length of the impulse response of your equalization filter. Then use either overlap-add or overlap-save (fast convolution methods/algorithms) to re-combine your IFFT results.
Also, if you want a strictly real result (no non-zero imaginary numbers), make sure that the input to your IFFT is conjugate symmetric.
I am trying to extract a sinusoid which itself has a speed which changes sinusiodially. The form of this is approximately sin (a(sin(b*t))), a+b are constant.
This is what I'm currently trying, however it doesnt give me a nice sin graph as I hope for.
Fs = 100; % Sampling rate of signal
Fc = 2*pi; % Carrier frequency
t = [0:(20*(Fs-1))]'/Fs; % Sampling times
s1 = sin(11*sin(t)); % Channel 1, this generates the signal
x = [s1];
dev = 50; % Frequency deviation in modulated signal
z = fmdemod(x,Fc,Fs,fm); % Demodulate both channels.
plot(z);
Thank you for your help.
There is a bug in your code, instead of:
z = fmdemod(x,Fc,Fs,fm);
You should have:
z = fmdemod(x,Fc,Fs,dev);
Also to see a nice sine graph you need to plot s1.
It looks like you are not creating a FM signal that is modulated correctly, so you can not demodulate it correctly as well using fmdemod. Here is an example that does it correctly:
Fs = 8000; % Sampling rate of signal
Fc = 3000; % Carrier frequency
t = [0:Fs]'/Fs; % Sampling times
s1 = sin(2*pi*300*t)+2*sin(2*pi*600*t); % Channel 1
s2 = sin(2*pi*150*t)+2*sin(2*pi*900*t); % Channel 2
x = [s1,s2]; % Two-channel signal
dev = 50; % Frequency deviation in modulated signal
y = fmmod(x,Fc,Fs,dev); % Modulate both channels.
z = fmdemod(y,Fc,Fs,dev); % Demodulate both channels.
If you find thr answers useful you can both up-vote them and accept them, thanks.