Reconstruction of Digital Signal using the sinc Function - matlab

I am trying to reconstruct the signal cos(2*pi*300e6) at the sampling frequency 800e6 using the sinc function in MATLAB. When I type in the following code, I'm instead getting something very noisy--not what I am looking for. What am I doing wrong? Thank you in advance!
Code:
F1 = 300e6;
Fs = 800e6;
tmin = 0;
tmax = 10/F1;
t = tmin:1e-12:tmax;
x1 = cos(2*pi*F1*t);
Ts = 1/Fs;
ts = tmin:Ts:tmax;
x1resampled = cos(2*pi*F1*ts);
x1reconstructed = zeros(1,length(t)); %preallocating for speed
samples = length(ts);
for i = 1:1:length(t)
for n = 1:1:samples
x1reconstructed(i) = sum(x1resampled(n)*sinc(pi*(t(i)-n*Ts)/Ts));
end
end
figure(1)
subplot(2,1,1)
plot(t,x1)
hold on
stem(ts,x1resampled)
subplot(2,1,2)
plot(t,x1reconstructed)

Two problems with the code:
You are not accumulating the reconstructed samples properly. Specifically, you are only retaining one value from the resampled signal, not all samples.
sinc in MATLAB uses the normalized sinc function. This means that you don't have to multiply the argument by pi. Recall that the reconstruction formula requires the normalized sinc function, so there is no multiplication of pi in the argument of the function.
Therefore you simply have to change the code inside the for loop:
F1 = 300e6;
Fs = 800e6;
tmin = 0;
tmax = 10/F1;
t = tmin:1e-12:tmax;
x1 = cos(2*pi*F1*t);
Ts = 1/Fs;
ts = tmin:Ts:tmax;
x1resampled = cos(2*pi*F1*ts);
x1reconstructed = zeros(1,length(t)); %preallocating for speed
samples = length(ts);
for i = 1:1:length(t)
for n = 1:1:samples
x1reconstructed(i) = x1reconstructed(i) + x1resampled(n)*sinc((t(i)-n*Ts)/Ts); %%% CHANGE
end
end
figure(1)
subplot(2,1,1)
plot(t,x1)
hold on
stem(ts,x1resampled)
subplot(2,1,2)
plot(t,x1reconstructed)
I now get this plot:
To make things more efficient, definitely use the sum function but do it over all samples. So your for loop should now be:
for i = 1:1:length(t)
x1reconstructed(i) = sum(x1resampled .* sinc((t(i) - (1:samples)*Ts) ./ Ts));
end

You can accomplish the same thing, but more efficiently, using the discrete Fourier transform (DFT):
F1 = 300e6;
Fs = 800e6;
tmin = 0;
tmax = 10/F1;
t = tmin:1e-12:tmax;
x1 = cos(2*pi*F1*t);
Ts = 1/Fs;
ts = tmin:Ts:tmax;
x1resampled = cos(2*pi*F1*ts);
x1resampledDFT = fftshift(fft(x1resampled));
n = (length(x1)-length(x1resampledDFT))/2;
x1reconstructedDFT = [zeros(1,ceil(n)),x1resampledDFT,zeros(1,floor(n))];
x1reconstructed = ifft(ifftshift(x1reconstructedDFT));
x1reconstructed = x1reconstructed / length(x1resampled) * length(x1reconstructed);
figure(1)
subplot(2,1,1)
plot(t,x1)
hold on
stem(ts,x1resampled)
subplot(2,1,2)
plot(t,x1reconstructed)
What is happening here is that I'm padding the DFT (as computed efficiently using fft) with zeros to the desired size. The inverse transform then results in the signal interpolated using the sinc interpolator. To preserve the signal strength some normalization is needed. Any differences you see with Rayryeng's answer is due to the periodic nature of the DFT: basically the sinc functions, as they exit the signal domain on the right, come back in at the left; the data at the right end of the plot influence the result at the left end of the plot and vice versa.
To learn more about interpolation using the Fourier transform, see this blog post.

Related

How to plot Gauss sums?

I'm trying to plot the Gauss sums according to the equation shown in the image s(t), but I keep receiving errors.
Can you please show me what am I doing wrong ?
%%
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sampling period
L = 1024; % Length of signal
t = 2*(0:L-1)*T; % Time vector
x = 0;
k = 0;
s = 0;
p = primes(L);
% s(t) = cumsum((k/p)(1:length(p)-1)).*exp(1i*k*t);
for k=1:p-1
s(t) = s(t) + (k/p).*exp(1i*k*t);
end
figure
subplot(2,2,1)
plot(t,s)
title('signal')
You're treating the Legendre symbol as fraction - which it is not despite the deceivingly similar appearance.
Furthermore the index for your summation doesn't make a whole lot of sense, you probably just wan to use s as summing variable. So you just have to replace k/p in your summation expression with the Legendre symbol.

(Fourier Transform) Simple DFT Result differs from FFT

I want to understand the discrete fourier transform by implementing it by myself.
While the result returned by my DFT is not correct the in matlab included version returns the correct frequencies of the original signal.
So the question is, where went I wrong. Is it a math or a implementation problem?
%% Initialisation
samples=2000;
nfft = 1024;
K = nfft / 2 + 1;
c = 264;
e = 330;
t = -1:1/samples:1-1/samples;
[~, N] = size(t);
f = (sin(2*c*pi*t)+cos(2*e*pi*t)).*exp(-pi*(2*t-1).^2);
X = zeros(nfft, 1);
%% Discrete Fourier Transform
if true
for k=1:nfft
for n=1:nfft
X(k) = X(k) + f(n)*exp(-j*2*pi*(k-1)*(n-1)/N);
end
end
else
X=fft(f, nfft);
end
R = abs(X(1:K));
[V,I] = sort(R,'descend');
F1 = samples*(I(1)-1)/nfft;
F2 = samples*(I(2)-1)/nfft;
disp(F1)
disp(F2)
plot(1:K, R, 1:K, real(X(1:K)), 1:K, imag(X(1:K)))
The issue lies in the number of samples for which the transform is done.
Xall = fft(f);
plot(abs(Xall(1:500)),'b');
hold on
plot(abs(X(1:500)),'r');
What you compute matches the result from the FFT done on all samples (i.e. with 4000 real samples in and 4000 complex values out).
Now, if you read the documentation of FFT with doc fft you will see that the signal is truncated if the output size is smaller than the input size. If you try:
Y = zeros(nfft, 1);
for k=1:nfft
for n=1:nfft
Y(k) = Y(k) + f(n)*exp(-1j*2*pi*(k-1)*(n-1)/nfft);
end
end
Y2 = fft(f(:),nfft); %make it a column
abs(sum(Y-Y2)) %6.0380e-12 , result within precision of the double float format

Correct frequency axis using FFT

How can I get the correct frequency vector to plot using the FFT of MATLAB?
My problem:
N = 64;
n = 0:N-1;
phi1 = 2*(rand-0.5)*pi;
omega1 = pi/6;
phi2 = 2*(rand-0.5)*pi;
omega2 = 5*pi/6;
w = randn(1,N); % noise
x = 2*exp(1i*(n*omega1+phi1))+4*sin(n*omega2+phi2);
h = rectwin(N).';
x = x.*h;
X = abs(fft(x));
Normally I'd do this :
f = f = Fs/Nsamples*(0:Nsamples/2-1); % Prepare freq data for plot
The problem is this time I do not have a Fs (sample frequency).
How can I do it correctly in this case?
If you don't have a Fs, simply set it to 1 (as in one sample per sample). This is the typical solution I've always used and seen everybody else use. Your frequencies will run from 0 to 1 (or -0.5 to 0.5), without units. This will be recognized by everyone as meaning "periods per sample".
Edit
From your comment I conclude that you are interested in radial frequencies. In that case you want to set your plot x-axis to
omega = 2*pi*f;

Matlab: convolution with bandpass filter does not cut the unwanted frequencies

I have a 6ms-long signal with three frequency components sampled at 60kHz:
fs = 60000;
T = 0.006;
t = 0:1/fs:T;
x = 0.3*sin(2*pi*2000*t) + sin(2*pi*5000*t) + 0.4*sin(2*pi*8000*t);
I have a bandpass filter with impulse response being the difference between two sinc functions:
M = 151;
N = 303;
n = 0:(N-1);
h = (sin(0.5760*pi*(n-M))-sin(0.3665*pi*(n-M)))./pi./(n-M);
h(n==M) = 0.2094;
I designed a function that convolves the input with filter:
function y = fir_filter(h,x)
y = zeros(1,length(x)+length(h)-1);
for i = 1:length(x)
for j = 1:length(h)
y(i+j-1) = y(i+j-1) + x(i)*h(length(h)-j);
end
end
And then applied the filter:
y = fir_filter(h,x);
This produced strange results:
figure(21)
ax1 = subplot(311);
plot(x);
title('Input Signal');
ax2 = subplot(312);
plot(h);
title('FIR');
ax3 = subplot(313);
plot(y);
title('Output Signal');
linkaxes([ax1,ax2,ax3],'x')
ax2.XLim = [0,length(y)];
Since the filter is bandpass, only one frequency component was expected to survive.
I tried to use yy = filter(h,1,[x,zeros(1,length(h)-1)]); and yyy = conv(h,x); and got the same results.
Please, can anybody explain me what I am doing wrong? Thank you!
Your passband does not cover any of the three signal frequency components. This can be seen directly on the graph (the second figure, containing the impulse response, has too fast variations compared with the signal). Or it can be seen from the numbers 0.5760 and 0.3655 in
h = (sin(0.5760*pi*(n-M))-sin(0.3665*pi*(n-M)))./pi./(n-M);
Why did you choose those numbers? The normalized frecuencies of the signal are [2 5 8]/60, that is, 0.0333 0.0833 0.1333. They are all below the passband [.3665 .5760]. As a result, the filter greatly attenuates the three components of the input signal.
Say you want to isolate the center frequency component (f = 5000 Hz, or f/fs = 0.08333 normalized frequency). You need a bandpass filter than lets that frequency through, and rejects the others. So you would use for example a normalized passband [.06 .1]:
h = (sin(0.06*pi*(n-M))-sin(0.1*pi*(n-M)))./pi./(n-M);
h(n==M) = (h(n==M+1)+h(n==M-1))/2; %// auto adjustment to avoid the 0/0 sample
A second problem with your code is that it gives two errors because you index h with 0. To solve this, change
n = 0:(N-1);
to
n = 1:N;
and
y(i+j-1) = y(i+j-1) + x(i)*h(length(h)-j);
to
y(i+j-1) = y(i+j-1) + x(i)*h(length(h)-j+1);
So, the modified code to isolate the central frequency component is:
fs = 60000;
T = 0.006;
t = 0:1/fs:T;
x = 0.3*sin(2*pi*2000*t) + sin(2*pi*5000*t) + 0.4*sin(2*pi*8000*t);
M = 151;
N = 303;
n = 1:N; %// modified
h = (sin(0.06*pi*(n-M))-sin(0.1*pi*(n-M)))./pi./(n-M); %// modified
h(n==M) = (h(n==M+1)+h(n==M-1))/2; %// modified
y = zeros(1,length(x)+length(h)-1);
for i = 1:length(x)
for j = 1:length(h)
y(i+j-1) = y(i+j-1) + x(i)*h(length(h)-j+1); %// modified
end
end
figure(21)
ax1 = subplot(311);
plot(x);
title('Input Signal');
ax2 = subplot(312);
plot(h);
title('FIR');
ax3 = subplot(313);
plot(y);
title('Output Signal');
linkaxes([ax1,ax2,ax3],'x')
ax2.XLim = [0,length(y)];
The result is as follows.
As can be seen, only the central frequency component is present in the output signal.
It's also observed that the envelope of the output signal is not constant. That's because the duration of the input signal is comparable to the filter lenght. That is, you are seeing the transient response of the filter. Note that the envelop rise times is approximately the length of the filter's impulse response h.
It's interesting to note an interesting trade-off here (signal processing is full of trade-offs). To make the transient shorter you could use a wider passband (filter length is inversely proportional to passband). But then the filter would be less selective, that is, it would have less attenuation at the unwanted frequencies. For example, see the result with passband [.04 .12]:
As expected, the transient is now shorter, but the desired frequency is less pure: you can see some "modulation" caused by remains of the other frequencies.

implement low pass filter in matlab

I want to implement a filter that eliminates higher frequencies. In this example I want to eliminate the sin curve and keep the linear curve.
EDIT:
I corrected my code, however the function that I implemented for filtering changes the edges of the data significantly which is not acceptable.
clc; clear all;
xaxis = linspace(1, 10, 1000);
data = xaxis + sin(xaxis*3);
Nf = 2^12;
xAxisf = linspace(-10,10,Nf);
% plot(xaxis, data);
% FFT
xsize = numel(data);
Xf = zeros([1 Nf]);
indices = Nf/2-floor(xsize/2):Nf/2-floor(xsize/2)+xsize - 1;
Xf(indices) = data;
% Xf = fftshift(Xf);
Xf = fft(Xf);
Xf = fftshift(Xf);
% plot
Xfa = abs(Xf); plot(xAxisf, Xfa);
% generate super-gaussian filter function
Nf = numel(Xf);
widthfilter = 0.12;
filterpower = 2;
filter = exp(-(xAxisf.^2./widthfilter^2).^filterpower);
% filter
filtertimes = 20;
Xf = Xf .* filter.^filtertimes;
% plot
Xfa = abs(Xf); plot(Xfa);
% iFFt
Xfs = ifftshift(Xf);
Xif = ifft(Xfs);
% Xif = ifftshift(Xif);
result = abs(Xif);
plot(result(indices))
First issue:
Xf = fftshift(data); % NOT NEEDED
Xf = fft(Xf);
Xf = fftshift(Xf);
Do not fftshift the data before fft. The shift is only needed AFTER fft. This is because the radix-n(probably 2) fft "decimates" the data in the process. You don't need to fix it before because it hasn't been decimated.
Second issue:
Xfs = ifftshift(Xf);
Xif = ifft2(Xfs);
Xif = ifftshift(Xif); % NOT NEEDED
ifftshift re-decimates the data (undoes fftshift), which ifft requires as input. The output of ifft reconstructs the original signal if the input is already decimated. DO NOT ifftshift after.
Third issue:
Xfs = ifftshift(Xf);
Xif = ifft2(Xfs); % USE ifft INSTEAD OF ifft2
Xif = ifftshift(Xiff);
Why in the world did you switch to 2D ifft all of a sudden?
I didn't look at your filter code in detail, but I would like to remark that if you want a low pass filter, it needs to be symmetric around the mid point. Otherwise your frequency response is not symmetric and you're gonna end up with at bunch of imaginaries.
And please change your title. This isn't a "Fourier filter". It is a low pass filter using the window method and fft. Window in that you're applying a window in frequency space.
Ok, it's late and I am getting cranky from the back and forth... just trying to help. Faster for me to just write the code for you.
If you're looking for an effect of the filter in your code, you're not gonna be able to because the cut off frequency of your filter is too high and/or the frequency of the sine wave in your data is too low. Here is a version where I increased the frequency of oscillation of the input sine wave:
clc; clear all;
xaxis = linspace(1, 10, 1000);
data = xaxis + sin(xaxis*10);
% plot(xaxis, data);
% FFT
Xf = data;
Xf = fft(Xf);
Xf = fftshift(Xf);
% generate super-gaussian filter function
Nf = numel(data);
xAxisf = linspace(-5,5,Nf);
widthfilter = 0.1;
filterpower = 2;
filter = exp(-(xAxisf.^2./widthfilter^2).^filterpower);
% filter
filtertimes = 1;
Xf = Xf .* filter.^filtertimes;
% plot
Xfa = abs(Xf); plot(Xfa);
% iFFt
Xfs = ifftshift(Xf);
Xif = ifft(Xfs);
result = abs(Xif);
plot(result); hold on; plot(data,'r');
legend('filtered','data');
going to bed. good night! did my public service :p