I want to calculate the frequency of time series precisely with at least 3 decimal value. This is a simple example that calculates the frequency of integer values.
#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;
}
But how should I change the code if I have
signal = 1.0*sin(50.350 * 2.0 * M_PI * theta[i]) +
0.5*sin(80.455 * 2.0 * M_PI * theta[i]);
Is it appropriate to change the units of time and frequency?
for example time in 1000*s
and frequency in kHz
?
Just changing the numbers in sin
will shift your lines from 50 and 80 to 50.350 and 80.455 Hz, and assuming you have 1024 lines by 1024 Hz. But you still have 1Hz resolution. You need more lines (x1000) by the same sampling frequency to get bigger resolution.
For example if you want 1/4 Hz resolution you need 4x more samples so by 1024 Hz sample rate you need fs * 4
samples:
...
#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
...