Issue with Time-Domain Shifting Using Fourier Shift Property in MATLAB

7 views (last 30 days)
I am trying to implement time-domain shifting using the Fourier shift property. Below is my MATLAB code:
% Parameter Setting
R = 618e3;
V = 7600;
lambda = 0.0313;
Fa = 5000;
N = 10000;
time_delay = 6.135e-5;
% Axis Setting
ta = ( -N/2 : N/2-1 )/Fa;
fa = ( -N/2 : N/2-1 )*( Fa/N );
s1 = exp(-1j*2*pi/lambda*(V^2*(ta + time_delay).^2)/R);
s2 = exp(-1j*2*pi/lambda*(V^2*(ta - time_delay).^2)/R);
% s1 Shifting
s1 = fftshift(fft(s1,N));
s1 = s1.*exp(-1j*2*pi.*fa.*time_delay);
s1 = ifft(ifftshift(s1),N);
% s2 Shifting
s2 = fftshift(fft(s2,N));
s2 = s2.*exp(1j*2*pi.*fa.*time_delay);
s2 = ifft(ifftshift(s2),N);
Result = s1 - s2;
figure(1);
plot(ta,abs(Result)); xlabel("t(s)");
title('After Substraction');
According to the Fourier shift theorem, the signals s1 and s2 should be identical. However, the result shows that the values in the center region are small, while the values on both sides are unexpectedly large.
I am not sure which part of my implementation is incorrect. I would greatly appreciate any guidance or suggestions to help me resolve this issue.
Thanks!

Answers (2)

David Goodmanson
David Goodmanson on 28 Feb 2025
Edited: David Goodmanson on 28 Feb 2025
Hi Jason,
I believe the main issue here is that your time waveform has significant frequency content that exceeds the nyquist frequency, so there will be aliasing. Your time waveform is an oscillatory function of the form
y = exp(2*pi*i*( f0*t + b*t^2))
The effective time-dependent frequencies can be found with
f = (1/(2pi i)) d/dt log(y) = f0 + 2bt
The nyquist frequency f_ny is half the sampling frequency = 2500 Hz. Ignoring f0 and with
b = V^2/(lambda R)
then the time for which aliasing occurs is approximately
t = f_ny lambda R / (2 V^2) = .4186
and as you can see that is right around where your plot starts having problems.
Even if there were no aliasing, I don't think this is a real good example of the time shift, because the delay you are using is quite small and the function itself is highly oscillatory with constant amplitude so it is hard to know what is going on. If you create gaussians by replacing the times sign with a minus sign in a couple of places as done below, and also increase the time delay then you get the following:
% Parameter Setting
R = 618e3;
V = 7600;
lambda = 0.0313;
Fa = 5000;
N = 10000;
%time_delay = 6.135e-5;
time_delay = 6.135e-2; % bigger time delay
% Axis Setting
ta = ( -N/2 : N/2-1 )/Fa;
fa = ( -N/2 : N/2-1 )*( Fa/N );
% gaussians, replace * with -
s1 = exp(-1j*2*pi/lambda-(V^2*(ta + time_delay).^2)/R);
s2 = exp(-1j*2*pi/lambda-(V^2*(ta - time_delay).^2)/R);
% S1 Shifting ------------------- original shift version commented out
% s1a = fftshift(fft(s1,N));
% s1a = s1a.*exp(-1j*2*pi.*fa.*time_delay);
% s1a = ifft(ifftshift(s1),N);
s1a = fft(ifftshift(s1,N));
s1a = ifftshift(fftshift(s1a).*exp(-1j*2*pi.*fa.*time_delay));
s1a = fftshift(ifft(s1a),N);
% s2 Shifting -------------------- original shift version commented out
% s2 = fftshift(fft(s2,N));
% s2 = s2.*exp(1j*2*pi.*fa.*time_delay);
% s2 = ifft(ifftshift(s2),N);
s2a = fft(ifftshift(s2,N));
s2a = ifftshift(fftshift(s2a).*exp(1j*2*pi.*fa.*time_delay));
s2a = fftshift(ifft(s2a),N);
figure(1)
plot(ta,abs([s1;s2;s1a;s2a]))
grid on
Here the red and blue curves are the original time-delayed (or advanced) ones, and the yellow and purple curves are shifted to delay = 0. (You can't see the yellow because the yellow and purple are overlays).
The code you have for the time shifting seems to provide no time shift. I commented them out and went to something similar but different.
  2 Comments
Jason
Jason on 28 Feb 2025
Thank you very much for your assistance!
I would like to ask a few more questions.
First, regarding the shifting process, I noticed that the way you applied the FFT is different from the approach I originally used. Could you please explain what was wrong with my initial method?
Additionally, I understand that aliasing is the reason the final result appears incorrect! However, due to practical considerations, I am unable to change the sampling rate (Fa) and the length of the time axis (ta), as these are determined by certain radar parameters.
Given these constraints, if I want to eliminate the time delay between signals s1 and s2 so that they become identical, is there any alternative method I could try to achieve this?
David Goodmanson
David Goodmanson on 2 Mar 2025
Edited: David Goodmanson on 2 Mar 2025
Hi Jason,
As to the first question, as you know the fft and ifft operate on functions whose arguments arrays are nonshifted
t = (0:N)/Fa f = (0:N)*(Fa/N)
and your arrays, including the phase factor, were created with shifted arrays
ta = (-N/2:N/2-1 )/Fa; fa = (-N/2:N/2-1)*(Fa/N);
Fftshift shifts a zero up-> to the center of the array. Ifftshift shifts a zero at the center of the array <-down to the origin. These two functions are the same for even N, but not for odd N.
The process I used is the same as what Paul did in his answer, but I will use his placement of fftshift and ifftshift because I think it is more clear
% make s1 origin-based, do fft, go back to center-based
s1a = fftshift(fft(ifftshift(s1,N)));
% phase is already center-based, multiply by phase
s1a = s1a.*exp(-1j*2*pi.*fa.*time_delay);
% make s1a origin-based, do ifft, go back to center-based
s1a = fftshift(ifft(ifftshift(s1a,N)));
Since you mentioned now that you have a radar chirp signal, I see that the gaussian example is not very useful. I'm still thinking about the second question.

Sign in to comment.


Paul
Paul on 2 Mar 2025
Edited: Paul on 2 Mar 2025
Hi Jason,
I think the fundamental issue is that one shouldn't expect that Result = 0.
Suppose we have a continuous time signal s(t).
Then we form
s1(t) = s(t + t_d)
s2(t) = s(t - t_d)
Taking Fourier transforms we have
S1(w) = exp(1j*w*t_d)S(w) (1)
S2(w) = exp(-1j*w*t_d)S(w)
So, we could multiply S1(w) and S2(w) by the inverse exponentials to recover S(w), and therefore s(t), from either.
But, when working with the DFT/iDFT (implemented by fft and ifft) we have to apply a window before sampling. In this case, the window, w(t), is rectangular from -1 <= t <= 1 (sorry for the abuse of notation between frequency (w) and window function (w(t)) ). So we really have
s1p(t) = s(t + t_d)w(t) (2)
and similarly for s2(t).
Therefore, the Fourier transform of s1p(t) does not have the form of (1), so we can't expect to recover S(w) by multiplying S1p(w) by the complex exponential.
In fact, we see that if we take the Fourer transform of (2) and then multipily the complex exponential, we get
S1r(w) = exp(-1j*w*t_d)*S1p(w)
with inverse transform
s1r(t) = s1p(t - t_d) = s(t)w(t - t_d)
which is our base signal multiplied by a shifted window (and similarly for s2r(t)).
So we shouldn't expect the s1r(t) - s2r(t) to be zero. It will really be
D(t) = s1r(t) - s2r(t) = s(t) ( w(t - time_delay) - w(t + time_delay) )
And that's before we get to issues with sample rates (as identified by @David Goodmanson in his Answer) and circular convolution, as discussed below.
Let's look at the problem in continuous time
% Parameter Setting
R = 618e3;
V = 7600;
lambda = 0.0313;
time_delay = 6.135e-5;
I'll leave this line commented and come back to it at the end.
%time_delay = time_delay/7.327705350067282e+00*7;
Define the base signal
syms s(t)
assume(t,'real')
theta = 2*sym(pi)/lambda*V^2/R*t^2;
s(t) = exp(-1j*theta);
Define a numerical function for later use
sfunc = matlabFunction(s);
Define the shifted functions
syms s1(t) s2(t)
s1(t) = s(t + time_delay);
s2(t) = s(t - time_delay);
Define the window
syms w(t)
a = 1;
w(t) = rectangularPulse(-a,a,t);
Continuous-time Fourier transforms,
syms S1p(omega) S2p(omega)
S1p(omega) = fourier(s1(t)*w(t),t,omega);
S2p(omega) = fourier(s2(t)*w(t),t,omega);
Multiply by the complex exponentials to compensate for the time delay AS IF the s1(t) and s2(t) are not windowed.
S1r(omega) = exp(-1j*omega*time_delay)*S1p(omega);
S2r(omega) = exp(+1j*omega*time_delay)*S2p(omega);
Go back to time domain
s1r(t) = ifourier(S1r(omega),omega,t);
s2r(t) = ifourier(S2r(omega),omega,t);
We actually didn't need to go through all that because we already know what s1r(t) (and s2r(t)) should be, which we can verify, but maybe it was instructive.
simplify(s1r(t) - s(t)*w(t - time_delay))
ans = 
0
Compute the difference
D(t) = simplify(s1r - s2r)
D(t) = 
Df = matlabFunction(D); % define a numerical function for later use
We see that D(t) is composed of a complex exponential multiplied by a heaviside sum that's strictly real. So we can plot the magnitude of D by plotting the magnitude of the second term over the time interval of interest
Dc = children(D);
figure
fplot(abs(Dc{2}),[-1,1],'-o'),grid
xlim([-1.1,1.1])
D(t) is zero, EXCEPT at the endpoints, which will be an important point below.
In order to use discrete-time processing, we need to define the sampling frequency (inspired by @David Goodmanson)
First we get the instantaneous frequency as a function of time
frequency(t) = diff(theta,t); % rad/sec
By the nature of the signal, we know the maximum frequency occurs at the end of the window.
maxfrequency = frequency(1);
maxfrequency = maxfrequency/2/sym(pi); % Hz
Define an initial guess for the sampling frequency as 20x the max frequency in the signal. Note that we also need the sampling frequency to be large enough to capture the effect of the delay.
Fa = double(20*maxfrequency);
Ts = 1/Fa;
Get an integer number of points that will cover the length of the window (N is odd, which is nice for symmetry)
N = round(2/Ts)
N = 238883
Define the sampled time vector over the window of interest
ta = linspace(-1,1,N);
Get the actual sampling period and frequency.
Ts = ta(2)-ta(1);
Fa = 1/Ts;
Define the corresponding frequency vector
nvec = (-(N-1)/2:(N-1)/2);
fa = nvec*(Fa/N);
Note that time_delay is not an integer multiple of the sampling period, but at least Fa is large enough so that the delay is roughly 7 samples and so will be apparent on the plots below.
Ndelay = time_delay/Ts
Ndelay = 7.3277
Samples of the delayed and windowed signals
%s1 = exp(-1j*2*pi/lambda*(V^2*(ta + time_delay).^2)/R);
%s2 = exp(-1j*2*pi/lambda*(V^2*(ta - time_delay).^2)/R);
s1 = sfunc(ta + time_delay);
s2 = sfunc(ta - time_delay);
In discrete-time, mulitiplication in the frequency domain by exp(-1j*2*pi*f*n0) corresponds to a circular shift of n0 samples in the time domain. Recall from above that fthe signal that we are recovering from this process, D, is very significant at both ends. Hence, the circular shift would cause the points on the left to couple over to the right, and the points on the right to couple over to the left after muliplication by exp(-1j*2*pi*f*n0) in the frequency domain. The way to mitigate this is to zero-pad the signals on both ends in the time domain, then process, then extract the central portion. This way, the circular shift is just shifting zeros around. Here I'll zero pad with 1e3 samples, though that might be excessive for this problem
Npad = 1e3;
npad = 1:Npad;
nvecpad = [-fliplr(npad) + nvec(1),nvec, nvec(end) + npad];
The corresponding frequency vector is
fapad = nvecpad*(Fa/numel(nvecpad));
And the zero-padded signals are
s1 = [0*npad,s1,0*npad];
s2 = [0*npad,s2,0*npad];
Now we do the FFT stuff. I believe the original code was missing a couple of shift operations, which I've added below.
% s1 Shifting
%s1 = fftshift(fft(s1,N));
S1 = fftshift(fft(ifftshift(s1)));
S1 = S1.*exp(-1j*2*pi.*fapad.*time_delay);
%s1 = ifft(ifftshift(s1),N);
s1r = fftshift(ifft(ifftshift(S1)));
Extract the part we care about
s1r = s1r(Npad+1:end-Npad);
% s2 Shifting
%s2 = fftshift(fft(s2,N));
S2 = fftshift(fft(ifftshift(s2)));
S2 = S2.*exp(1j*2*pi.*fapad.*time_delay);
%s2 = ifft(ifftshift(s2),N);
s2r = fftshift(ifft(ifftshift(S2)));
s2r = s2r(Npad+1:end-Npad);
The resulting difference looks a lot like the continuous-time plot above based on the symbolic stuff.
Result = s1r - s2r;
figure;
plot(ta,abs(Result),'-o'); xlabel("t(s)");
title('After Substraction');
Zoom in at both endpoints and compare magnitude and phase of the discrete-time result to the continuous-time result
figure
h1 = subplot(211);
h1.NextPlot = 'add';
h2 = subplot(212);
h2.NextPlot = 'add';
plot(h1,ta,abs(Result),'-o')
xlim(h1,[-1.0002,-0.9998])
plot(h1,ta,abs(Df(ta)),'-x')
plot(h2,ta,abs(Result),'-o')
xlim(h2,[0.9998,1.0002])
plot(h2,ta,abs(Df(ta)),'-x')
We see that the continuous-time signal amplitude is a step function at both ends, as expected from the heaviside sum in D. The discrete-time processing kind of recovers the same amplitude.
figure
h1 = subplot(211);
h1.NextPlot = 'add';
h2 = subplot(212);
h2.NextPlot = 'add';
plot(h1,ta,angle(Result),'-o')
xlim(h1,[-1.0002,-0.9998])
plot(h1,ta,angle(Df(ta)),'-x')
plot(h2,ta,angle(Result),'-o')
xlim(h2,[0.9998,1.0002])
plot(h2,ta,angle(Df(ta)),'-x')
The phase matches well in the region where the amplitude is large.
Why don't the amplitude and phase match better? I'm pretty sure it's because the time_delay is not an integer multiple of Ts (see Ndelay above) and therefore the multiplication by the complex exponentials in the discrete frequency domain isn't really doing what we we'd like it to do. To see this, you can uncomment the commented time_delay line at the top of the code, which will force time_delay to be exactly 7 samples, which will make the above plots look much better. There will still be some error, which I think is just due to numerical innaccuracy.
Summary: The fundamental approach for recovering s(t) isn't quite right, and if we still want to proceed down the discrete-time processing path, we need choose a high-enough sampling frequency and understand the effect of multiplying by exp(-1j*w*N0) in the discrete-frequency domain.
  2 Comments
Jason
Jason on 3 Mar 2025
Thank you very much for your help. I never realized that discrete-time processing involves considering so many aspects. May I ask, If it is known that the signal is aliasing, what methods would you recommend to eliminate the time delay in the equations s1 and s2?

Sign in to comment.

Products


Release

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!