Java 理解FFT输出

Java 理解FFT输出,java,fft,Java,Fft,我目前正忙于实习,老板希望我在周末之前准备好一个用java编程的FFT 现在我已经从普林斯顿大学得到了FFT的代码: 我在我的项目中实现并扩展了这段代码,现在我能够首先读取信号的二进制输入,然后对这个样本值进行FFT处理,然后提供幅值 现在我来谈谈我的问题。 我输入了我用final double d=Math.sin(I)生成的以下值并循环8次(这只是为了测试,下周我将不得不输入实际值) 因此,这些值来自纯正弦(我不知道正确的英语单词,但对于纯正弦,我指的是只有一个频率的正弦,例如50Hz) 现

我目前正忙于实习,老板希望我在周末之前准备好一个用java编程的FFT

现在我已经从普林斯顿大学得到了FFT的代码:

我在我的项目中实现并扩展了这段代码,现在我能够首先读取信号的二进制输入,然后对这个样本值进行FFT处理,然后提供幅值

现在我来谈谈我的问题。 我输入了我用
final double d=Math.sin(I)生成的以下值并循环8次(这只是为了测试,下周我将不得不输入实际值)

因此,这些值来自纯正弦(我不知道正确的英语单词,但对于纯正弦,我指的是只有一个频率的正弦,例如50Hz)

现在输出为

0.553732750242242
2.3946469565385193 - 2.0970118573701813i
-1.386684423934684 + 0.9155598966338983i
-0.8810419659226628 + 0.28041399267903344i
-0.8075738836045867
-0.8810419659226628 - 0.28041399267903366i
-1.386684423934684 - 0.9155598966338983i
2.394646956538519 + 2.0970118573701817i
以及输出的大小

0.553732750242242
3.183047718211326
1.6616689248786416
0.9245901540720989
0.8075738836045867
0.924590154072099
1.6616689248786416
3.183047718211326
现在,我实际上期望在每个频率采样点的输出值为0,直到我达到纯正弦占主导地位的频率,其中输出值应大于0(例如,在50 Hz时)。至少这是我老板给我这个任务时所期望的

总结: 这就是我正在努力解决的问题。我读过另一篇关于类似问题的帖子,但仍然有一些问题没有回答。我应该如何处理给定的输出数据?如何找到最频繁发生的频率

我真的需要一些帮助或解释我的想法哪里是错的


感谢收听…

在应用简单窗口函数后计算512点傅里叶变换:

w(i)= ((float)i-(float)(n-1f)/2f)
它在i=25时给出峰值(结果数组上的最大幅值)

输入中还添加了更多信息,如正弦波发生器的频率(50 Hz)和采样率(1kHz或每个样本0.001秒),并添加了2PI常数:

初始化现在看起来像这样(作为sin(2xPIxFxi)表示法):

现在这些步骤在频率空间中,输入频率为1kHz,因此您可以感知最大500 Hz的谐波信号(采样率的一半)

另外,结果范围为0到N/2,另一半为镜像,将可感知频率范围(500)除以结果范围(256表示N=512)得到

误差的很大一部分必须是在开始时使用的窗口函数,但v2[26]的值高于v2[24],因此实际拾取值更接近v2[26],这些点的平滑图形应显示50 Hz

忽略结果数组的第一个元素,因为它是关于恒定信号电平、无限波长或零频率的

以下是dft计算代码,以确保fft是否返回正确的结果:

//a---->b Fourier Transformation brute-force
__kernel void dft(__global float *aRe,
                  __global float *aIm,
                  __global float *bRe,
                  __global float *bIm)
{
    int id=get_global_id(0); // thread id
    int s=get_global_size(0); // total threads = 512
    double cRe=0.0f;
    double cIm=0.0f;
    double fid=(double)id;
    double fmpi2n=(-2.0*M_PI)*fid/(double)s;
    for(int i=0;i<s;i++)
    {
            double fi=(float)i;
            double re=cos(fmpi2n*fi);
            double im=sin(fmpi2n*fi);

            cRe+=aRe[i]*re-aIm[i]*im;
            cIm+=aRe[i]*im+aIm[i]*re;
    }

    bRe[id]=cRe;
    bIm[id]=cIm;
}
//a--->b傅里叶变换蛮力
__内核无效dft(uu全局浮点*为,
__全球浮动*目标,
__全球浮动*bRe,
__全局浮点*bIm)
{
int id=get_global_id(0);//线程id
int s=get_global_size(0);//线程总数=512
双cRe=0.0f;
双cIm=0.0f;
双fid=(双)id;
双fmpi2n=(-2.0*M_-PI)*fid/(双)s;
对于(int i=0;ib逆傅里叶变换蛮力
__内核无效idft(_全局浮点*为,
__全球浮动*目标,
__全球浮动*bRe,
__全局浮点*bIm)
{
int id=get_global_id(0);//线程id
int s=get_global_size(0);//线程总数=512
双cRe=0.0f;
双cIm=0.0f;

对于(int i=0;i@Winterwurst此外,若峰值不是您所预见的位置,您可以尝试在板内微调两个整数之间的峰值位。
for (int i = 0; i < n; i++)
{ 
         v1[i] = ((float)i-(float)(n-1f)/2f)*
             (float)Math.Sin(0.001f* 50f*2f*Math.PI*(float)i);
                               ^      ^  ^                 ^
                               |      |  |                 |
                               |      F  |                 |
                           sampling      2xPi constant   sample bin
                           rate(simulation)
}
v2[22] 2145,21852033773  
v2[23] 3283,36245333956  
v2[24] 6368,06249969329  
v2[25] 28160,6579468591    <-- peak
v2[26] 23231,0481898687  
v2[27] 1503,8455705291  
v2[28] 1708,68502071037  
25
25*500 = 12500
48.83 Hz
//a---->b Fourier Transformation brute-force
__kernel void dft(__global float *aRe,
                  __global float *aIm,
                  __global float *bRe,
                  __global float *bIm)
{
    int id=get_global_id(0); // thread id
    int s=get_global_size(0); // total threads = 512
    double cRe=0.0f;
    double cIm=0.0f;
    double fid=(double)id;
    double fmpi2n=(-2.0*M_PI)*fid/(double)s;
    for(int i=0;i<s;i++)
    {
            double fi=(float)i;
            double re=cos(fmpi2n*fi);
            double im=sin(fmpi2n*fi);

            cRe+=aRe[i]*re-aIm[i]*im;
            cIm+=aRe[i]*im+aIm[i]*re;
    }

    bRe[id]=cRe;
    bIm[id]=cIm;
}
// a--->b inverse Fourier Transformation brute force
__kernel void idft(__global float *aRe,
                   __global float *aIm,
                   __global float *bRe,
                   __global float *bIm)
{
    int id=get_global_id(0); // thread id
    int s=get_global_size(0); // total threads = 512
    double cRe=0.0f;
    double cIm=0.0f;
    for(int i=0;i<s;i++)
    {
        double re=cos(2.0*M_PI*((double)id)*((double)i)/(double)s);
        double im=sin(2.0*M_PI*((double)id)*((double)i)/(double)s);

        cRe+=aRe[i]*re-aIm[i]*im;
        cIm+=aRe[i]*im+aIm[i]*re;
    }
    cRe/=(double)s;
    cIm/=(double)s;
    bRe[id]=cRe;
    bIm[id]=cIm;
}