【问题标题】:Matlab: fourier coefficients of sign() function are oscillatingMatlab:sign()函数的傅立叶系数正在振荡
【发布时间】:2019-02-18 11:30:11
【问题描述】:

我正在编写一个接收时变信号并返回 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])

这是结果图:

请注意,已知的虚构解决方案是 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;

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

【问题讨论】:

  • 重复问题使用不同的函数,但与您面临的问题完全相同:FFT 假定原点 (t=0) 是输入数组中的第一个元素。您正在计算移位阶跃函数的 FFT。
  • 这个问题并不是真正的重复:首先,我的时间表示为零,这就是他们帖子中的问题。其次,我的主要问题是 FT 的振荡行为,而不是镜面反射,如我的标题所示。但我会编辑我的 Q 以提及该帖子。
  • @CrisLuengo Cris 我读过它:......正如你在那里写的那样“FFT 期望原点位于第一个(最左边)样本。这就是 ifftshift 的用途:”所以我做了什么在我修改后的问题中,我的第一个时间点是 0。我认为这将消除对iffshift的需要。现在将更仔细地研究这一点。
  • @CrisLuengo 为什么这个极其简单的解决方案适用于单位脉冲函数(无需花费时间等),具有华丽的情节,但是当我用一个单一的做完全相同的事情时阶跃函数,是灾难吗? stackoverflow.com/questions/19717779/… 那就是为什么那里的答案如此简单易行。我只是没有看到区别(特别是考虑到一个脉冲只是两个符号的总和!)。
  • 我错了,你有这个问题,还有第二个问题。对不起。看我的回答。您在此处链接的单位脉冲问题绘制了傅立叶变换的幅度,因此看不到信号的变化。

标签: matlab fft


【解决方案1】:

你的代码有两个问题:

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

  2. DFT 假设(可以解释为假设)输入信号是周期性的。这导致了第二次大跳跃。基本上,您的信号看起来像一个移位的框函数,因此您的变换看起来像一个修改相位的 sinc 函数。解决方案是在调用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

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

【讨论】:

  • 所以基本上我选择了一个最糟糕的函数来开始建立我对 FFT 的直觉。 :)
猜你喜欢
  • 2012-05-18
  • 1970-01-01
  • 2016-03-25
  • 2016-07-13
  • 2013-01-31
  • 2019-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多