FFTW просто не будет возвращать значения, отличные от бесконечности, значения, приближающиеся к нулю, или отрицательную бесконечность

Я пытаюсь рассчитать ДПФ синусоиды на 20 Гц.

Сначала я заполняю std :: vector 10 циклами функции синуса с частотой 20 Гц:

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];
}

Затем я вычисляю БПФ:

fftw_execute(p);

После расчета БПФ я проверяю результаты и убираю.

    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;
}

Я ожидал бы всплеска около 20 Гц, однако никакого всплеска нет вообще. Все возвращаемые значения всегда равны нулю, бесконечности или отрицательной бесконечности. Моей первой мыслью было, что ввод перезаписывается сам, но после ввода проверьте правильность ввода. Я пытался запустить FFTW в разных режимах, FFTW_FORWARD, FFTW_BACKWARD, FFTW_ESTIMATE, FFTW_RELATIVE, ничего не помогает. Я пытался вычислить различные функции синуса на разных частотах, частоты дискретизации, количество циклов.

Грустная часть — то, что я смог заставить это работать однажды. Затем я продолжил работать, увидел, что он не работает, затем снова открыл файл, который работал, и теперь он больше не работает!

Кто-нибудь еще сталкивался с этим?

РЕДАКТИРОВАТЬ: НОВЫЙ КОД КАК ПРЕДЛОЖЕНИЯ

Это все еще не работает. Я попытался инициализировать мнимую часть комплексных чисел равной 0, и у меня все еще была та же проблема, поэтому вот код, использующий реальную функцию in / complex out библиотеки 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;

}

3

Решение

Вы выделяете массив fftw_complexes, которые состоят из двух элементов — реального и сложного компонентов — но вы только инициализируете реальный компонент каждого образца. Это, вероятно, оставляет сложные компоненты, содержащие случайные данные, вызывая неожиданные сумасшедшие результаты!

Если вам не нужно иметь дело со сложными образцами — что, вероятно, — вы можете использовать одна из функций DFT для реальных данных FFTW, который занимает double массив в качестве ввода. В противном случае инициализируйте все сложные компоненты (in[i][1]) к нулю.

Кроме того, вы не смотрите на сложную составляющую вывода. Там может быть что-то важное, что вы упускаете.

6

Другие решения

Ваш вклад — 10 периодов чистой синусоидальной волны. Это означает:

  • Ваш выход чисто мнимый вызвано нечетной синусоидальной функцией (sin (x) = -sin (-x))
    В случае функции косинуса результат был чисто реальным
    потому что косинус является четной функцией (cos (x) = cos (-x)
  • Есть только две частотные линии, один в положительной полосе частот
    и один в отрицательной группе.
  • Поскольку у вас есть 10 периодов на входе, ваши строки должны произойти
    на выходе [10] [1] и на выходе [N-10] [1]
    .
  • Поскольку вы не нормализовали выходной сигнал, а количество выборок равно 500,
    амплитуды должны быть вне [10] [1] = -250 и вне [490] [1] = +250.
  • Все остальные значения должны быть нулевыми.
1

По вопросам рекламы [email protected]