在FFT之后,在时域中延迟信号,频域中的相位变化

时间:2015-07-23 12:02:48

标签: matlab signal-processing fft

我遇到了在Matlab脚本中实现的基本时间/频率属性的问题。 该物业是:

im1

我试图在Matlab脚本中实现这一点。 我认为频率值为5Hz的正弦信号,采样频率等于800Hz,我希望将此信号延迟1.8秒。 所以我已经实现了这个脚本:

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');

输出图是:

output plot

问题出在哪里?如何实现正确的时间延迟?

由于

3 个答案:

答案 0 :(得分:1)

问题不在于实现,而在于FFT的属性(分别是DFT):你发布的时间延迟的公式是正确的,但你必须记住,你正在做的事情循环移位。这意味着从2.2s到4.0s的所有信号部分将被复制到输出的开头。这正是你所看到的:

before

您想要的信号从1.8秒开始,但是从0到0.6837秒,由于循环移位而插入的部分。小计算:您的输入信号为1 x 3201,即它将使用895个零进行零填充。在几秒钟内,这是1.1187秒的零。循环移位将在开头插入最后的1.8s,即1.8 - 1.1187 = 0.86秒不会为零但包含正弦。这正是我们在情节中看到的数量。

为了避免这种影响,您必须用至少为延迟信号的零点填充输入信号。在您的情况下将是

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));

这给了我们

result

答案 1 :(得分:0)

我相信您需要采用更大的FFT来适应移位/延迟。您可以通过使用适当数量的零(使用您提供的采样频率和延迟量,> 1440)对输入进行零填充来强制执行此操作。然后你得到了理想的结果。

Sine shift with pad

你原来的情节有尾巴缠绕,因为FFT / IFFT限制在4096个分档,这不足以合并整个移位信号+前导零。

答案 2 :(得分:0)

你可以试试这个:

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');

考虑使用矢量化实现,您可以摆脱for-loop

结果如下:

enter image description here