FFT后如何得到幅度和对应的频率

Posted

技术标签:

【中文标题】FFT后如何得到幅度和对应的频率【英文标题】:How to get magnitude and corresponding frequency after FFT 【发布时间】:2016-07-18 11:08:56 【问题描述】:

在数据集上执行 FFT 后如何获得幅度和相应的频率。我需要绘制数据集的幅度与频率。另外,为什么我们将 FFT 数组的大小增加为实际数据集大小的两倍?然后生成的输出数组的大小再次不同,请帮助我理解这个 FFT 代码。此外,何时执行复前 FFT 以及何时执行实前 FFT?两者的区别?我需要对数据集执行 FFT 并获得 FFT 后的幅度以及每个幅度的相应频率。

                int length = data.length;
                FloatFFT_1D fftDo = new FloatFFT_1D(length);
                float[] fft = new float[length * 2];
                System.arraycopy(data, 0, fft, 0, length);
                fftDo.complexForward(fft);
                //for(double d: fft) 
                    //System.out.println(d);
                //
                float outputfft[] = new float[(fft.length+1)/2];
                if(fft.length%2==0)
                    for(int i = 0; i < length/2; i++)
                        outputfft[i]= (float) Math.sqrt((Math.pow(fft[2*i],2))+(Math.pow(fft[(2*(i))+1], 2)));
                    
                else
                    for(int i = 0; i < (length/2)+1; i++)
                        outputfft[i]= (float) Math.sqrt((Math.pow(fft[2*i],2))+(Math.pow(fft[(2*i)+1], 2)));
                    
                
                for (float f : outputfft) 
                    System.out.println(f);
                

【问题讨论】:

请添加堆栈跟踪 length / 2 +1 != length +1 / 2 ... float outputfft[] = new float[(data.length+1)/2]; vs for(int i = 0; i &lt; length/2+1; i++) 感谢您的回复。但我真的不明白为什么数组大小不同。我已经修改了我的问题,试图更清楚地说明我真正想要的是什么。我是 Java 新手,也是 FFT 新手。如果可以的话,请帮助我理解代码。我刚刚尝试从各种来源复制它并尝试在我的数据集上实现它。但是即使在进行了您建议的更改后也无法使其工作。不知道如何添加堆栈跟踪..你的意思是在每一步都打印输出吗? 好的,退一步... Stacktrace 是发生异常时得到的输出。所有那些“BlahblahException at ... at ... at ...”大多数时候它会将您带到实际错误隐藏的地方。 数组大小可能不同,因为您有两种计算方法:a) length / 2 +1 和 (length+1)/2 它们可能采用不同的四舍五入方式。为避免该错误,您可以简单地使用您在 for 条件中使用的数组:for(int i=0; i&lt;outputfft.length;i++) 【参考方案1】:

根据定义,实值数据向量的 FFT 是复杂且对称的。如果您有 N 个样本的向量长度,您将获得 N 个频率数据的 FFT,其频率由 Fs/N 分隔,其中 Fs 是采样频率。您的输出向量是两倍大小,因为复杂数据是交错的 [re,im,re,im ...]。 输出数据是对称的一半大小,您只需要查看频率对应的前半部分 [0 .. Fs/2] 上半部分是 [-Fs/2 .. 0)

如果您有一个偶对称输入数据,X(-n)=X(n),或奇对称,X(-n)=-X(n),您可以使用 realForward 函数

【讨论】:

感谢您的解释。因此,在我的问题中提到的代码中,我的数据长度为 N,输出向量 fft[] 的长度为 (2N),那么 outputfft[] 的输出数据的长度为 (N+1)。 . 不是真的数据大小的一半吗?另外,能否告诉我如何从 fft? 的输出中检索频率,以及 realForward fft 和 complexForward fft 之间的区别? 在您的代码中,输出的长度为 (N+1)/2,我想它是为奇数长度的输入数据保留空间。频率向量从 0 开始,间隔为 Fs/N [0 Fs/N 2Fs/N 3Fs/N ...] @Aqua 实际上,您的输出向量应该与您的输入向量具有相同的大小。只是它是复数。因此,您有两种可能性:1. 通过添加 0 或 2 的虚部来使输入也“复杂”。将输出放大两倍以考虑交错的 Real 和 Img 部分。 零可能是因为该频率中没有数据。但正如我所说,“数据点”的数量必须相同。但除此之外:请仍然将您的堆栈跟踪添加到问题中。

以上是关于FFT后如何得到幅度和对应的频率的主要内容,如果未能解决你的问题,请参考以下文章

Java - 使用 FFT 查找音频信号的频率和幅度

在进行 FFT 和改变频率分量值之后,我只会在音频中得到噪音。我哪里错了?

如何获得 FFT 中每个值的频率?

如何实时获取特定频率音频信号的幅度android

使用许多紧凑频率时出现奇怪的 FFT 峰值

NAudio FFT 返回所有频率的小而相等的幅度值