Matlab:符号()函数的傅里叶系数是振荡的

Matlab:符号()函数的傅里叶系数是振荡的,matlab,fft,Matlab,Fft,我正在写一个函数,它接收时变信号并返回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

我正在写一个函数,它接收时变信号并返回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/jw
,或
j(-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;

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

您的代码有两个问题:

  • DFT(FFT算法计算DFT)将原点放在最左边的bin中。创建<代码> yVals<代码>,使原点位于中间,使输出频谱成为一半长度的信号,这会导致非常高的频率振荡。修正是在调用<代码> FFT之前,在输入数据上使用<代码> ifftSHIFT < /代码>。/p>
  • DFT假设(可解释为假设)输入信号是周期性的。这会导致第二次大跳跃。基本上,您的信号看起来像一个移位的box函数,因此您的变换看起来像一个具有修改相位的sinc函数。解决方案是在调用
    fft
    之前对输入应用一个加窗函数。请参阅示例

  • 按如下方式修改您的代码:

    yvals = sign(tvals);
    yvals = yvals .* hanning(numel(yvals), 'periodic').'; % Apply windowing function
    
    % ...
    
    fftInitial = fft(ifftshift(yvals)); % Shift signal before calling FFT
    
    这是您的代码现在提供的输出:


    重复问题使用不同的函数,但与您面临的问题完全相同:FFT假设原点(t=0)是输入数组中的第一个元素。您正在计算一个移位步长函数的FFT。这个问题实际上不是重复的:首先,我的时间表示中有一个零,这是他们文章中的问题。其次,我的主要问题是FT的振荡行为,而不是镜像反射,如我的标题所示。但我我会编辑我的Q以提及那篇文章。@CrisLuengo Cris我读过:……正如你在那里写的,“FFT期望原点在第一个(最左边)样本上。这就是ifftshift的作用:因此,我在修改后的问题中所做的只是将0作为我的第一个时间点。我认为这将消除iffshift的必要性。现在我们将更仔细地研究这个问题。@CrisLuengo为什么这个极其简单的解决方案适用于单位脉冲函数(不需要处理时间之类的问题),有着华丽的情节,但当我用单步函数做完全相同的事情时,这是一场灾难?也就是说,为什么答案如此简单和容易。我只是看不到区别(特别是考虑到一个脉冲只是两个信号的总和!).我错了,你有这个问题,但还有第二个问题。对不起,请看我的答案。你在这里链接的单位脉冲问题绘制了傅里叶变换的幅度,因此无法看到信号中的位移。因此,基本上我选择了最差的函数之一,开始建立我对FFT的直觉。:)