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

时间:2018-09-13 17:10:06

标签: matlab fft

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

它对于真正简单的正弦波总和非常有效。

对于其他模拟信号,例如阶跃函数,我最终得到了一些fubar,它们以锯齿状的方式振荡。这是一个使用重边阶跃函数的最小示例,该函数绘制了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])

这是结果图: enter image description here

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

请注意,除了锯齿之外(这是我最关心的问题),这些砝码的信封似乎都没有遵循。实际上,它似乎在原点周围翻转了。不知道我在这里做错了什么组合。

基于一些有用的反馈,人们指出了这个问题:
Analytical Fourier transform vs FFT of functions in Matlab

尤其是,在时间数组中不包含零可能会引起问题,这是此处的主要问题。我的代码中的时间数组包含零,因此它看起来不像是重复的。我通过时移步骤将零推到了数组的前面(尽管坦白地说,我没有做很多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 个答案:

答案 0 :(得分:3)

您的代码有两个问题:

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

  2. DFT假定(可以解释为假设)输入信号是周期性的。这导致第二次大跳跃。基本上,您的信号看起来像是移位盒函数,因此您的变换看起来像是具有修改相位的正弦函数。解决方案是在调用fft之前,将窗口功能应用于输入 。例如,参见this other question

如下修改代码:

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

% ...

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

这是您的代码现在提供的输出:

graph