Matlab:sign()函数的傅立叶系数在振荡

Matlab: fourier coefficients of sign() function are oscillating

我正在编写一个接收时变信号和 returns FFT 的函数。它遵循 Matlab 文档:

它适用于非常简单的正弦曲线求和。

对于其他模拟信号,如阶跃函数,我最终得到了一些 fubar,它以类似锯齿的方式振荡。这是一个使用 heaviside 阶跃函数的最小示例,它绘制了 FFT 权重的虚部:

%Create and plot sign function 
Fs = 1000;
dt = 1/Fs;
tvals = -1: dt: 1-dt;
yvals = sign(tvals); %don't use heaviside() it is very slow

subplot(2,1,1);
    plot(tvals, yvals, 'k', 'LineWidth', 2); hold on; 
    axis([-1 1 -1.1 1.1]);

%Calculate center-shifted FFT and plot imaginary part
fftInitial = fft(yvals);
n = length(fftInitial);
dF = Fs/n;
frequenciesShifted = -Fs/2: dF: Fs/2-dF;  %zero-centered frequency range
fftShifted = fftshift(fftInitial/length(yvals));

subplot(2,1,2);
plot(frequenciesShifted, imag(fftShifted), 'b', 'LineWidth', 2);hold on
xlim([-8 8])

这是结果图:

请注意,假想解已知为 2/jwj(-2/w)

请注意,除了我最关心的锯齿波之外,这些权重的 包络线 甚至似乎都没有跟随它。它实际上似乎围绕原点翻转。不确定我在这里做错了什么。

根据一些有用的反馈,人们指出了这个问题:

特别是,时间数组中不包含零可能会导致问题,这是那里的主要问题。我代码中的时间数组包含一个零,因此它看起来不像是重复的。我通过时移步骤将我的零推到数组的前面(尽管坦率地说我已经做了很多 fft() 而没有这样做而且它们看起来都很好,所以我不认为这是问题所在,但是我现在只想将其作为一个问题删除)。所以我们最终得到:

Fs = 1000;
dt = 1/Fs;
tvals = 0: dt: 2-dt;
yvals = sign(tvals-1); %don't use heaviside() it is very slow
zeroInd = find(yvals == 1, 1, 'first');
yvals(zeroInd-1) =0;
%Calculate center-shifted FFT and plot imaginary part
fftInitial = fft(yvals);
n = length(fftInitial);
dF = Fs/n;
frequenciesShifted = -Fs/2: dF: Fs/2-dF;  %zero-centered frequency range
fftShifted = fftshift(fftInitial/length(yvals));

%Plot stuff
subplot(2,1,1);
plot(tvals, yvals, 'k', 'LineWidth', 2); hold on; 
axis([0 2 -1.1 1.1]);  
subplot(2,1,2);
plot(frequenciesShifted, imag(fftShifted), 'b', 'LineWidth', 2);hold on
xlim([-8 8])
grid on;

我仍然得到相同的之字形函数和相同的错误信封。因此,虽然我确实看到我的问题和那个问题密切相关,但我不确定它们是否重复。而且我真的很想能够画出这些组件值的半途合理的图(我确实处理了一些基本上是阶跃函数的生理信号(它们移动 非常 快与我的测量仪器相比,所以这对我来说不仅仅是一个学术练习。

您的代码有两个问题:

  1. DFT(FFT算法计算DFT)取原点在最左边的bin。创建 yvals 使原点位于中间会导致输出频谱成为信号偏移一半长度的频谱。这会导致非常高频的振荡。解决方法是在 调用 fft 之前对输入数据 使用 ifftshift。查看更多

  2. DFT假设(可以理解为假设)输入信号是周期性的。这导致了第二次大跳跃。基本上,您的信号看起来像一个移位盒函数,因此您的变换看起来像一个具有修改相位的 sinc 函数。解决方案是在调用 fft 之前 对输入应用窗口函数 。例如参见 [​​=16=].

修改你的代码如下:

yvals = sign(tvals);
yvals = yvals .* hanning(numel(yvals), 'periodic').'; % Apply windowing function

% ...

fftInitial = fft(ifftshift(yvals)); % Shift signal before calling FFT

这是您的代码现在给出的输出: