【问题标题】:Size in JTransform's FFT compared to MATLAB与 MATLAB 相比,JTransform 的 FFT 中的大小
【发布时间】:2012-02-20 20:44:09
【问题描述】:

我目前正在使用 JTransforms 库来计算 FS 为 44100 Hz 的一秒信号的 DFT。代码很简单:

DoubleFFT_1D fft = new DoubleFFT_1D(SIZE);
fft.complexForward(signal);                 // signal: 44100 length array with audio bytes.

有关 JTransform 的 DoubleFFT_1D 类的文档,请参阅此页面。 http://incanter.org/docs/parallelcolt/api/edu/emory/mathcs/jtransforms/fft/DoubleFFT_1D.html

问题是:SIZE 应该是什么?我知道这可能是窗口大小,但似乎无法让它与我遇到的最常见的值一起使用,例如 1024 和 2048。

目前我正在通过生成 1kHz 正弦信号来测试此功能。但是,当我使用上面的代码并将结果与​​ MATLAB 的fft-函数进行比较时,它们似乎来自完全不同的数量级。例如。 MATLAB 给出的结果如0.0004 - 0.0922i,而上述代码的结果如-1.7785E-11 + 6.8533E-11i,SIZE 设置为2048。但是信号数组的内容是相等的。

SIZE 的哪个值会提供与 MATLAB 的内置 fft 类似的 FFT 函数?

【问题讨论】:

    标签: java matlab fft


    【解决方案1】:

    根据文档,SIZE 看起来应该是signal 中的样本数。如果它确实是 44.1 kHz 的 1 s 信号,那么您应该使用SIZE = 44100。由于您使用的是复杂数据,signal 应该是一个两倍大小的数组(实数/虚数顺序)。

    如果您不使用SIZE = 44100,您的结果将与Matlab 给您的不匹配。这是因为 Matlab(可能还有 JTransforms)根据输入的长度缩放 fftifft 函数的方式 - 不要担心幅度不匹配。默认情况下,Matlab 使用完整信号计算 FFT。您可以向fft(在 Matlab 中)提供第二个参数来计算 N 点 FFT,它应该与您的 JTransforms 结果相匹配。


    从您的 cmets 看来,您正在尝试创建一个 spectrogram。为此,您必须权衡:光谱分辨率、时间分辨率和计算时间。这是我的(Matlab)代码,用于 1 秒频谱图,针对 1 秒信号的每个 512 个样本块计算。

    fs = 44100; % Hz
    w = 1; % s
    
    t = linspace(0, w, w*fs);
    k = linspace(-fs/2, fs/2, w*fs);
    
    % simulate the signal - time-dependent frequency
    f = 10000*t; % Hz
    x = cos(2*pi*f.*t);
    
    m = 512; % SIZE
    S = zeros(m, floor(w*fs/m));
    for i = 0:(w*fs/m)-1
        s = x((i*m+1):((i+1)*m));
        S(:,i+1) = fftshift(fft(s));
    end
    


    对于此图像,我们沿频率轴(y 轴)有 512 个样本,范围从 [-22050 Hz 22050 Hz]。沿时间轴(x 轴)有 86 个样本,覆盖约 1 秒。
    对于此图像,我们现在沿频率轴(y 轴)有 4096 个样本,范围从 [-22050 Hz 22050 Hz]。时间轴(x 轴)再次覆盖大约 1 秒,但这次只有 10 个块。

    快速时间分辨率(512 个样本块)还是高光谱分辨率(4096 个样本块)更重要,取决于您处理的信号类型。您必须决定在时间/光谱分辨率方面想要什么,以及在合理的计算时间内可以实现什么。例如,如果您使用 SIZE = 4096,您将能够计算出 ~10x/s 的频谱(基于您的采样率),但 FFT 可能不够快,无法跟上。如果您使用SIZE = 512,您的光谱分辨率会更差,但 FFT 的计算速度会更快,您可以计算出 ~86x/s 的光谱。如果 FFT 仍然不够快,您可以开始跳过块(例如,使用 SIZE=512 但只计算其他块,每 1 秒信号给出约 43 个频谱)。希望这是有道理的。

    【讨论】:

    • 它确实有效,但完成这项工作需要很长时间。我不认为这是应该的。不过还是谢谢。
    • “永远”是什么意思?您可以发布更多代码,以便我可以看到您在做什么吗?如果您输入真实数据并使用fft.realForwardFull,您应该会获得(很大)速度优势。
    • 我正在开发一个 Android 项目,并试图让 FFT 实时计算。这意味着,在下一秒记录时,会计算并显示当前的 FFT。不过,这需要一分钟多的时间。代码的其他部分用于过去的处理,但日志显示它是上面的代码一直在消耗。更具体地说,GC 似乎在 fft 计算期间广泛工作,并将 SIZE 设置为 44100(或 22050)。
    • 我想我现在明白了一点,请参阅上面的编辑。抱歉,如果我仍然没有理解您的观点 - 您的更多代码将有助于了解 signal 的更新频率,以及您在 FFT 之后对频率表示所做的操作。
    • 这实际上很有帮助。非常感谢,这让我对我得到的结果有了很多了解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-19
    • 2016-09-08
    • 1970-01-01
    • 2014-10-09
    • 2015-12-06
    • 2013-02-24
    相关资源
    最近更新 更多