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

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

我对在 Matlab 脚本中实现的基本 time/frequency 属性 有疑问。 属性 是:

我已经尝试在 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');

输出图是:

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

谢谢

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

您的原始图有尾部环绕,因为 FFT/IFFT 被限制为 4096 个箱,这不足以合并整个移位信号 + 前导零。

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

你要的信号确实是从1.8s开始的,但是0到0.6837s之间有部分是循环移位插入的。小计算:您的输入信号是 1 x 3201,即它将用 895 个零填充零。以秒为单位,这是 1.1187 秒的零。循环移位将在开头插入最后的 1.8 秒,即 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));

这给了我们

你可以试试这个:

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

结果如下: