难以理解 FFT 计算的相位。简短的 matlab 演示来说明

发布于 2024-12-12 19:57:31 字数 855 浏览 3 评论 0原文

我正在测试正弦信号和余弦信号的 fft 相位输出。 下面的脚本创建信号并对它们执行 FFT。幅度低于阈值的 bin 的相位谱归零,因为我只对信号的相位感兴趣。

% 10khz 10 second long time interval
t = 0:1 / 10000:10;

%1khz cos
c = cos(2 * pi * 1000 .* t);
%1khz sin
s = sin(2 * pi * 1000 .* t);

%ffts
C = fft(c)/length(c);
S = fft(s)/length(s);

%magnitude and phases of ffts
CA = abs(C); %cos magnitude
SA = abs(S); %sin magnitude

Cthresh = max(CA) * 0.5;
Sthresh = max(SA) * 0.5;

%find all indeces below the threshold
Crange = find(CA < Cthresh);
Srange = find(SA < Sthresh);

%set the indeces below the threshold to 0 - phase will be meaningless for
%noise values
CP = angle(C);
CP(Crange) = 0;
SP = angle(S);
SP(Srange) = 0;

如果绘制 CP(cos 的相位),您将在与 cos 信号频率相对应的箱中得到 0.3142 的相位,而其他地方为零。这是 pi/10。我期待着得到 pi。这是为什么呢?

如果绘制 SP,您将得到 1.2566 的值。我期望得到 pi/2 或 1.5708。预期值的80%。是什么导致了这些错误?

I'm testing the phase output of an fft of a sin signal and a cos signal.
The script below creates the signals and performs an FFT on them. Bins who's amplitude is below a threshold are zeroed for the phase spectrum because I am only interested in the phase of the signals.

% 10khz 10 second long time interval
t = 0:1 / 10000:10;

%1khz cos
c = cos(2 * pi * 1000 .* t);
%1khz sin
s = sin(2 * pi * 1000 .* t);

%ffts
C = fft(c)/length(c);
S = fft(s)/length(s);

%magnitude and phases of ffts
CA = abs(C); %cos magnitude
SA = abs(S); %sin magnitude

Cthresh = max(CA) * 0.5;
Sthresh = max(SA) * 0.5;

%find all indeces below the threshold
Crange = find(CA < Cthresh);
Srange = find(SA < Sthresh);

%set the indeces below the threshold to 0 - phase will be meaningless for
%noise values
CP = angle(C);
CP(Crange) = 0;
SP = angle(S);
SP(Srange) = 0;

If you plot CP - the phase of the cos - you will get a phase of 0.3142 in the bins corresponding to the frequency of the cos signal and zeros elsewhere. This is pi/10. I'm expecting to get pi. Why is this?

If you plot SP you get values of 1.2566. I'm expecting to get pi/2 or 1.5708. 80% of the expected value. What is causing these errors?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

表情可笑 2024-12-19 19:57:31

如果您的输入信号在 FFT 孔径长度上不是完全周期性的(完整周期的精确整数),则正弦曲线在 FFT 孔径两端将是不连续的。因此,您将得到一个相位,它是 FFT 输入向量两端两个不同相位的平均值。

如果您想要更合理的相位,请将正弦波的相位参考 FFT 输入向量的中心,并在 FFT 之前进行 fft 移位。这将导致在零相位参考位置处出现连续的正弦曲线,并且具有单相而不是奇怪的平均值。

另请注意,matlab 可能会将相位引用为采样正弦曲线中的第二个点(例如,vectorElement[i=1]),而不是第一个点(vectorElement[i=0])。对于周期 = 20 个样本的正弦曲线,其相位为 pi/10。

If your input signal is not perfectly periodic in the FFT aperture length (an exact integer number of full periods), the sinusoids will be discontinuous across the ends of the FFT aperture. Thus you will get a phase that is the average of the two different phases at both ends of the FFT input vector.

If you want a more sensible phase, reference the phase of your sinusoids to the center of the FFT input vector, and do an fft shift before the FFT. This will result in a continuous sinusoid at the zero phase reference position, with a single phase instead of a weird average value.

Also note that matlab may reference the phase to the second point in a sampled sinusoid, e.g. vectorElement[i=1], not the first, vectorElement[i=0]. This will have a phase of pi/10 for a sinusoid of period = 20 samples.

ぃ双果 2024-12-19 19:57:31

您遇到的问题正是 hotpaw2 所说的。 t 中有 100001 个样本,因此没有完美的周期信号,因此存在泄漏。这意味着您从隐式矩形窗口中获得了一个 sin()/sin() 函数,与您的解决方案进行了卷积。这就是改变你的阶段的原因。

如果您尝试以下操作:

t = 0:1 / 10000:9.9999;
c = cos(2 * pi * 1000 .* t);
%1khz sin
s = sin(2 * pi * 1000 .* t);
%ffts
C = fft(c)/length(c);
S = fft(s)/length(s);

您会发现余弦的相位为零(这正是您所期望的),而正弦的相位为 pi/2。

在时域中执行线性移位(使用fftshift)只会在频域中引入线性相位项,并且不会解决原始问题。

实际上,如果要在频域中检查信号,则应应用加窗,而不是尝试精确设置序列的长度以匹配信号的周期。在这种情况下,您确实应该确保信号适当对齐,以便窗口衰减端点,从而消除不连续性。这具有展宽 FFT 主瓣的效果,但它也控制了泄漏。

The issue you have is exactly what hotpaw2 has stated. You have 100001 samples in t, so you do not have a perfectly periodic signal, therefore you have leakage. That means that you've got a sin()/sin() function from your implicit rectangular window convolved with your solution. That's what changes your phase.

If instead you try the following:

t = 0:1 / 10000:9.9999;
c = cos(2 * pi * 1000 .* t);
%1khz sin
s = sin(2 * pi * 1000 .* t);
%ffts
C = fft(c)/length(c);
S = fft(s)/length(s);

you would find that the phase of the cosine is zero (which is what you would expect) and that the phase of sine is pi/2.

Performing a linear shift in the time domain (using fftshift) will merely introduce a linear phase term in the frequency domain, and will not resolve the original problem.

In practice, rather than trying to set the length of the sequence precisely to match the period of the signal, windowing should be applied if the signal is to be examined in the frequency domain. In that case you really should make sure that your signals are appropriately aligned so that the window attenuates the end points, thus smoothing out the discontinuity. This has the effect of broadening the main lobe of the FFT, but it also controls the leakage.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文