简体   繁体   中英

Delay a signal in time domain with a phase change in the frequency domain after FFT

I have a problem with a basic time/frequency property implemented in a Matlab script. The property is:

IM1

I've tried to implement this in a Matlab script. I've supposed a sinusoidal signal with 5Hz of frequency value, Sampling frequency equal to 800Hz and I want to delay this signal by 1.8 seconds. So I've implemented this script:

Fs = 800;
Time_max = 4; % seconds
t = 0:(1/Fs):Time_max;
delay = 1.8; % One second of delay

f = 5; %Hz
y = sin(2 * pi * f * t);

figure
subplot(2,1,1)
plot(t,y);
xlabel('time (s)')
legend('Original');

%FFT
SIZE = 2^nextpow2(length(y));
Y = fft(y,SIZE);

df = Fs/SIZE;
f= -Fs/2:df:Fs/2 - df;

for k = 1:SIZE

    Y(k) = Y(k)*exp(-(1i*2*pi*f(k)*delay));

end

subplot(2,1,2)
plot(real(ifft(Y)),'r')
legend('Shifted');

And the output plot is :

输出图

Where is the problem? How can I achieve the correct time delay?

Thanks

The problem is not in the implementation, but lies within the properties of the FFT (respectively of the DFT): The formula you posted for a time delay is correct, but you have to keep in mind, that it you are doing a circular shift . This means that all the signal parts from 2.2s to 4.0s will be copied to the beginning of the output. This is exactly what you see:

之前

The signal you want does start at 1.8s, but from 0 to 0.6837s there is the part which is inserted due to the circular shift. Small calculation: your input signal is 1 x 3201 , ie it will be zero-padded with 895 zeros. In seconds, this is 1.1187 seconds of zeros. The circular shift will insert the last 1.8s at the beginning, ie 1.8 - 1.1187 = 0.86 seconds will not be zeros but contain a sine. This is exactly the amount we see in the plot.

To avoid this effect, you have to pad the input signal with at least the amount of zeros by which you delay the signal. In your case that would be

Fs = 800;
Time_max = 4; % seconds
t = 0:(1/Fs):Time_max;
delay = 1.8; % One second of delay

f = 5; %Hz
y = sin(2 * pi * f * t);
y = [y, zeros(1,delay*Fs)];          % Zero-pad the signal by the amount of delay

SIZE = 2^nextpow2(length(y));
Y = fft(y,SIZE);

df = Fs/SIZE;
f= -Fs/2:df:Fs/2 - df;

for k = 1:SIZE
    Y(k) = Y(k)*exp(-(1i*2*pi*f(k)*delay));
end

td = (0:SIZE-1)/Fs;
yd = real(ifft(Y));

Which gives us

结果

I believe you need to take a larger FFT to accommodate the shift/delay. You could force this by zero-padding the input with the proper number of zero's (> 1440 with your provided sampling frequency and delay amount). Then you get the desired result.

用垫正弦移位

Your original plot had the tail wrapping around because the FFT/IFFT were limited to 4096 bins, which was not enough to incorporate the entire shifted signal + leading zeros.

You can try this:

Fs = 800;
Time_max = 4; % seconds
t = 0:(10/Fs):Time_max;
delay = 1.8; % One second of delay
f = 5; %Hz
y = sin(2 * pi * f * t);
figure;subplot(2,1,1);plot(t,y);xlabel('time (s)')
legend('Original');

w = 2*pi*f;
X=fft(y);
Y=X.*exp(-1i*w*(t+delay));
ynew = real(ifft(Y));
subplot(2,1,2);plot(ynew);
legend('Shifted');

Consider that using vectorized implementation, you can get rid of the for-loop .

the result would be such as follows:

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM