从(FFTW)的时间序列计算精确的非整数频率

时间:2018-02-19 10:33:03

标签: c++ fftw

我想用至少3个十进制值精确计算时间序列的频率。 这是一个计算整数值频率的简单示例。

#include <fftw3.h>
#include <cstdio>
#include <cmath>
#include <iostream>
#include <fstream>

#define REAL 0
#define IMAG 1
#define NUM_POINTS 1024


void acquire_signal(double *signal, double *theta) {
    /* Generate two sine waves of different frequencies and
     * amplitudes.
     */

    int i;
    for (i = 0; i < NUM_POINTS; ++i) {
        theta[i] = (double)i / (double)NUM_POINTS;
        signal[i] = 1.0*sin(50.0 * 2.0 * M_PI * theta[i]) +
                    0.5*sin(80.0 * 2.0 * M_PI * theta[i]);
    }
}

int main() {
    unsigned flags{0};
    double *theta  = new double[NUM_POINTS];
    double *signal = new double[NUM_POINTS];

    fftw_complex result[NUM_POINTS/2+1];

    fftw_plan plan = fftw_plan_dft_r2c_1d(NUM_POINTS,
                                         signal,
                                         result,
                                         flags);
    acquire_signal(signal,theta);
    fftw_execute(plan);

    //save signal and result
    std::ofstream f1,f2;
    f1.open ("signal.txt");
    for (int i=0; i<NUM_POINTS; i++){
        f1 <<theta[i]<<" "<<signal[i]<<"\n";
    }

    f1.close();
    f2.open("result.txt");

    for (int i=0; i<NUM_POINTS/2; i++){
        double yf = 2.0/(double)(NUM_POINTS)* sqrt(result[i][REAL]*result[i][REAL]+ result[i][IMAG]* result[i][IMAG]);
        f2<< (double)i << " "<<yf <<"\n";
    }
    f2.close();
    fftw_destroy_plan(plan);
    delete[] signal,theta;

    return 0;
}

enter image description here 但是,如果我有

,我应该如何更改代码
signal = 1.0*sin(50.350 * 2.0 * M_PI * theta[i]) +
         0.5*sin(80.455 * 2.0 * M_PI * theta[i]);

更改时间和频率的单位是否合适? 例如1000*s中的时间和kHz中的频率?

1 个答案:

答案 0 :(得分:0)

只需更改sin中的数字,就会将您的线路从50和80移至50.350和80.455 Hz,并假设您有1024线×1024赫兹。但你仍然有1Hz的分辨率。您需要更多的线(x1000)才能获得更高的分辨率。

例如,如果您想要1/4 Hz分辨率,则需要4倍以上的样本,因此,如果采样率为1024 Hz,则需要fs * 4个样本:

...

#define NUM_POINTS (1024 * 4)
double fs = 1024;  // Sample rate in Hz

void acquire_signal(double *signal, double *theta) {
    /* Generate two sine waves of different frequencies and
     * amplitudes.
     */

    int i;
    for (i = 0; i < NUM_POINTS; ++i) {
        theta[i] = (double)i / (double)fs;
        signal[i] = 1.0*sin(50.0 * 2.0 * M_PI * theta[i]) +
                    0.5*sin(80.0 * 2.0 * M_PI * theta[i]);
    }
}
....
for (int i=0; i< (NUM_POINTS/2 + 1) ; i++){
    double yf = 2.0/(double)(NUM_POINTS)* sqrt(result[i][REAL]*result[i][REAL]+ result[i][IMAG]* result[i][IMAG]);
    f2 << (double)i * fs / ( NUM_POINTS ) << " "<<yf <<"\n";
}
  

0 2.90715e-16

     

0.25 1.19539e-16

     

0.5 2.15565e-16

     

0.75 2.88629e-16

     

1 3.05084e-16

     

1.25 3.864e-16

     

...

     

49.75 9.47968e-16

     

50 1

     

50.25 1.12861e-15

     

50.5 4.95946e-16

     

50.75 6.9016e-16

     

...