我相信我非常接近答案,只需轻轻一推即可获得答案。
我想要什么:
我想获取一个信号,使用 FFT 将其转换为频域 (FD),然后将其乘以,然后将其转换回时域 (TD)。
我为什么要它:
因为这是我应该能够在我的位置上解决的问题,所以我想知道如何正确地解决它。而且因为用 Arduino 制作一个非常低端的频谱分析仪会很有趣,而不是发送脉冲,我可以发送一个步骤来代替,导出输出以获得脉冲响应。我知道我也可以发送方波并使用 Goertzel 滤波器并在方波中寻找基本正弦,但是......正如我之前所说。我想知道如何正确地做到这一点。
我尝试过的:
我想我会先选择最简单的情况,方波和三角波。
方波的傅立叶级数为:
三角波的傅里叶级数为:
三角波的导数是方波,从上面的等式可以清楚地看出,乘以相移每个正弦并正确放大每个正弦以消除一个因素。
我知道 0 Hz 分量的导数是 0,所以在 FD 中,我知道除了最高频率分量之外我需要将信号乘以的所有值,但我也将其设置为 0,因为我不知道不知道应该是什么。
我也知道,对于实值输入,频谱在中间镜像,并且频谱的后半部分只是前半部分的共轭。
这意味着我需要在 FD 中将信号与 32 bin FFT 相乘的向量在 matlab/octave 代码中看起来像这样:
derivative = [0,i*1:15,0,-i*15:-1:1]
%comments:
%0 = 0
%1:15 = 1,2...14,15
%15:-1:1 = 15,14...2,1
derived_signal = ifft(fft(signal).*derivative)
我的 make-a-sense-o-meter 说它是有道理的,但是当我将信号与它相乘时,我得到的结果非常接近导数,但不是 100% 正确。如果我乘以[0,-1,zeros(1,29),1]
一阶导数近似的 FFT,我会得到更好的结果。有关倍频程图,请参见下图。
这是我使用的代码,以防其他人想乱七八糟:
triangle=[linspace(-1,1,16),linspace(1,-1,16)];
subplot(1,2,1)
plot(0:31,triangle)
xticks([0 7 15 23 31])
axis([-1 32 -1.1 1.1])
title("32 point triangle wave")
grid
subplot(1,2,2)
hold on
dt_jw=real(ifft(fft(triangle).*[0,i*(1:15),0,-i*(15:-1:1)]));
plot(0:31,dt_jw)
dt_convolution=real(ifft(fft(triangle).*fft([0,-1,zeros(1,29),1])));
plot(0:31,dt_convolution)
axis([-1 32 -1.1 1.1])
xticks([0 7 15 23 31])
yticks([1 dt_jw(floor(length(dt_jw)/4)) dt_convolution(floor(length(dt_jw)/4)) 0 -1])
title("d/dt(triangle)")
legend("fft(tri)*jw","convolution with [-1,0,1]")
grid
hold off
我觉得我非常接近答案,并且我遗漏了一些非常明显的东西。
那么为什么乘以不把我的三角波变成漂亮的方波?因为到目前为止,用一阶导数近似对我的三角波进行卷积更有意义。