FFTW根本不会返回除无穷大以外的值,接近零的值或负无穷大

时间:2014-07-21 00:29:51

标签: c++ signal-processing fft fftw dft

我试图在20hz处计算正弦波的DFT。

首先,我用20赫兹的正弦函数填充一个std :: vector:

std::vector<double> sinx;
double samplerate = 1000.0;
double frequency = 20.0;
double num_cycles = 10.0;
for (int i=0; i<samplerate/frequency*num_cycles; i++){
    sinx.push_back(sin(2.0*M_PI*((double)i)*frequency/samplerate));
}
double N = sinx.size();

然后我启动FFTW输入和输出数组以及FFTW计划:

fftw_complex *in, *out;
fftw_plan p;

in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)* N);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);

然后我用正弦波函数值填充输入数组:

for (int i=0; i<N; i++){
    in[i][0] = sinx[i];
}

然后我计算FFT:

fftw_execute(p);

计算FFT后,检查结果并清理。

    double hz_per_index = samplerate/2.0/N*num_cycles;
for (int i=0; i<N/num_cycles; i++){
    std::cout<<"hz: "<<hz_per_index*i<<" out: "<<fabs(out[i][0])<<" "<<out[i][1]<<" in: "<<in[i][0]<<std::endl;
}

我预计20h左右会出现峰值,但根本没有尖峰。所有返回的值始终是零,无穷大或负无穷大。我的第一个想法是输入是覆盖自己,但在计算后检查输入并且它是正确的。我尝试在不同的模式下运行FFTW,FFTW_FORWARD,FFTW_BACKWARD,FFTW_ESTIMATE,FFTW_RELATIVE,没有任何帮助。我尝试过计算不同频率,采样率,周期数的不同正弦函数。

令人遗憾的是,我能够让它工作一次。然后我继续工作,看到它不起作用,然后重新打开有效的文件,现在它不再起作用了!

其他人遇到过这个?

编辑:根据建议编写新代码

它仍然无效。我尝试将复数的虚部初始化为0,我仍然有同样的问题,所以这里的代码利用了fftw库的真实输入/复合输出函数。

我基本上都是0。 这是输入的所有5个周期的完整输出,显示输入,输出和hz值:

https://gist.github.com/anonymous/ed419f4cfb43887c810e

double *in;
fftw_complex* out;
fftw_plan p;

std::vector<double> sinx;
double samplerate = 1000.0;
double frequency = 20.0;
double num_cycles = 5.0;
for (int i=0; i<samplerate/frequency*num_cycles; i++){
    sinx.push_back(sin(2.0*M_PI*((double)i)*frequency/samplerate));
}
int N = sinx.size();

in = (double*) fftw_malloc(sizeof(double)* N);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
p = fftw_plan_dft_r2c_1d(N, in, out, FFTW_ESTIMATE);

for (int i=0; i<N; i++){
    in[i] = sinx[i];
}

fftw_execute(p);

double hz_per_index = samplerate/2.0/N*num_cycles;
for (int i=0; i<N; i++){
    std::cout<<"hz: "<<hz_per_index * (i % (int)(N/num_cycles))<<" out: "<<out[i][0]<<" in: "<<in[i]<<std::endl;
}

fftw_destroy_plan(p);
fftw_free(in); fftw_free(out);

return 0;

}

2 个答案:

答案 0 :(得分:6)

您正在分配一个fftw_complex es数组,它由两个元素组成 - 真实和复杂组件 - 但您只是初始化每个样本的实际组件。这可能会使复杂的组件包含随机数据,从而导致意外的疯狂结果!

如果您不需要处理复杂样本(可能是这样),您可能需要使用one of FFTW's real-data DFT functions,它将double数组作为输入。否则,将所有复杂组件(in[i][1])初始化为零。

此外,您不会查看输出的复杂组件。你可能错过了一些重要的东西。

答案 1 :(得分:1)

您的输入是纯正的正弦波的10个周期。这意味着:

  • 您的输出是纯虚数由奇数正弦函数引起(sin(x)= -sin(-x)) 在余弦函数的情况下,输出是纯粹的 因为余弦是偶数函数(cos(x)= cos(-x)
  • 只有两个频率线,一个在正频段 还有一个在负面乐队中。
  • 因为您的输入中有10个句点,所以应该出现您的行 在[10] [1]和[N-10] [1]
  • 因为你没有规范化输出,样本数量是500, 幅度应该超出[10] [1] = -250并且[490] [1] = +250。
  • 所有其他值应为零。