До стрічки

Використання FFT у C/C++ для обробки сигналів

Дослідження продуктивності бібліотеки FFTW для обробки сигналів у C/C++ в порівнянні з Python. Висока ефективність використання ресурсів.

Використання FFT у C/C++ для обробки сигналів

У світі обробки сигналів та аналізу даних важливу роль відіграє швидке перетворення Фур'є (FFT). Після порівняння реалізацій FFT на Python та C/C++, стало очевидно, що бібліотека C FFTW є найпотужнішою. Різниця в продуктивності між двома аналогічними програмами на Python та C/C++ виявилася значною, як за навантаженням на процесор, так і за використанням оперативної пам'яті. Це важливо, оскільки на моєму Raspberry Pi програма на Python заповнювала оперативну пам'ять до блокування системи.

Реалізація FFT у C

Для того щоб реалізувати FFT у C, я скористався RTLSDR для збору даних. Ось основні кроки, які я виконав:

  1. Підключення бібліотеки FFTW:
    #include <fftw3.h>
    
  2. Визначення розміру FFT:
    #define CAPTURE 1000 // розмір FFT
    
  3. Оголошення змінних:
    fftw_complex *in;
    fftw_complex *out;
    fftw_plan p;
    

Налаштування FFT

Функція для налаштування FFT виглядає наступним чином:

void setFFT() {
    in = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * CAPTURE + 1);
    out = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * CAPTURE + 1);
    p = fftw_plan_dft_1d(CAPTURE, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
}

Обчислення спектру потужності

Функція для обчислення спектру потужності виглядає так:

double *fft(uint8_t *data, int *count, double *power_spectrum) {
    double *power_spectrum_tmp = (double *) malloc(sizeof(double) * CAPTURE + 1);
    fftw_complex *cx_power_spectrum = (fftw_complex *) malloc(sizeof(fftw_complex) * CAPTURE + 1);
    int w = 0;
    int x = 0;

    // Перетворення даних у комплексний формат
    for (int i = 0; i < CAPTURE * 2; i += 2) {
        in[x][0] = (data[i] / (255.0 / 2.0)) - 1.0;
        in[x][1] = (data[i + 1] / (255.0 / 2.0)) - 1.0;
        x++;
    }

    fftw_execute(p);

    // Обчислення спектру потужності
    for (int i = 0; i < CAPTURE; i++) {
        double complex complex_tmp = out[i][0] + out[i][1] * I;
        complex_tmp = conj(complex_tmp) * complex_tmp;
        cx_power_spectrum[w][0] = creal(complex_tmp);
        cx_power_spectrum[w][1] = cimag(complex_tmp);
        w++;
    }

    // Перетворення з комплексного формату в подвійний
    for (int i = 0; i < CAPTURE; i++)
        power_spectrum_tmp[i] = cx_power_spectrum[i][0];

    // Реорганізація даних
    for (int i = 0; i < CAPTURE / 2; i++)
        power_spectrum[i] = power_spectrum_tmp[i + (CAPTURE / 2)];
    for (int i = 0; i < CAPTURE / 2; i++)
        power_spectrum[i + (CAPTURE / 2)] = power_spectrum_tmp[i];

    free(power_spectrum_tmp);
    free(cx_power_spectrum);

    return power_spectrum;
}

Висновки

Використання FFTW у C/C++ дозволяє досягти значно кращої продуктивності в порівнянні з Python, що робить цю бібліотеку ідеальним вибором для обробки сигналів у реальному часі.