fft算法总结

前言

电赛期间总结的FFT算法

一、fft是什么?

FFT(Fast Fourier Transformation)是离散傅氏变换(DFT)的快速算法。即为快速傅氏变换。它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。 

二、使用步骤

电赛时总结的fft算法,经过实际测试,可用!

#include <assert.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>

#define LN 10
#define N (1 << LN)

#define M_PI 3.14159265358979323846

void fft_origin_sort(float *in_real, float *in_imag, float *out_real,
                     float *out_imag, uint32_t ln) {
  uint32_t LEN = 1 << ln;
  for (int i = 0; i < LEN; i++) {
    uint32_t _idx = 0;
    for (int j = 0; j < ln; j++) {
      _idx = (_idx << 1) | ((i >> j) & 0x01);
    }
    if (in_real != NULL && out_real != NULL) {
      out_real[i] = in_real[_idx];
    } else if (out_real != NULL) {
      out_real[i] = 0;
    }
    if (in_imag != NULL && out_imag != NULL) {
      out_imag[i] = in_imag[_idx];
    } else if (out_imag != NULL) {
      out_imag[i] = 0;
    }
  }
}

void fft_origin_Wn(float *Wn_real, float *Wn_imag, uint32_t ln) {
  uint32_t LEN = 1 << ln;
  for (int i = 0; i < LEN / 2; ++i) {
    float k = (float)i / (float)LEN;
    float a = k * (2.0 * M_PI);
    Wn_real[i] = cosf(a);
    Wn_imag[i] = -sinf(a);
  }
}

static inline void cpx_mul(float real1, float imag1, float real2, float imag2,
                           float *out_real, float *out_imag) {
  *out_real = real1 * real2 - imag1 * imag2;
  *out_imag = real1 * imag2 + real2 * imag1;
}

void fft_origin_cal(float *real, float *imag, float *Wn_real, float *Wn_imag,
                    uint32_t ln) {
  for (int i = 0; i < ln; ++i) {
    uint32_t m = 1 << (ln - 1 - i);
    uint32_t n = 1 << i;
    for (int j = 0; j < m; ++j) {
      for (int k = 0; k < n; ++k) {
        uint32_t _idx = j * n * 2 + k;
        uint32_t X2_idx = _idx + n, Wn_idx = k * m;
        float X2Wn_r, X2Wn_i;
        cpx_mul(real[X2_idx], imag[X2_idx], Wn_real[Wn_idx], Wn_imag[Wn_idx],
                &X2Wn_r, &X2Wn_i);
        real[X2_idx] = real[_idx] - X2Wn_r;
        imag[X2_idx] = imag[_idx] - X2Wn_i;
        real[_idx] = real[_idx] + X2Wn_r;
        imag[_idx] = imag[_idx] + X2Wn_i;
      }
    }
  }
}

float vmod(float r, float i) { return sqrtf(r * r + i * i); }

void base_freq(float *real, float *imag, uint32_t ln) {
  const float epsilon = 1e-2;
  float _diff = 0;
  uint32_t LEN = (1 << ln) / 2;
  float A[LEN];
  for (int i = 0; i < LEN; ++i) {
    A[i] = vmod(real[i], imag[i]) / LEN;
  }
  for (int i = 1; i < LEN; ++i) {
    float diff = A[i] - A[i - 1];
    if (_diff > epsilon && diff < -epsilon) {
      printf("%d,%f\n", i - 1, A[i - 1]);
      return;
    }
    _diff = diff;
  }
}

void genx(float *f, float k, uint32_t n) {
  for (int i = 0; i < n; ++i) {
    f[i] = sin(i * (M_PI * 2) / n * k) * 600;
  }
}

int main() {
  float Wn_r[N / 2], Wn_i[N / 2];
  float _r[N] = {0};
  float r[N], i[N];
  fft_origin_Wn(Wn_r, Wn_i, LN);
  for (int w = 1; w < N / 2 - 1; ++w) {
    genx(_r, w, N);
    fft_origin_sort(_r, NULL, r, i, LN);
    fft_origin_cal(r, i, Wn_r, Wn_i, LN);
    base_freq(r, i, LN);
  }
}


总结

电赛中的仪器仪表类或者信号处理类题目经常要进行对信号的处理,其中最常见的就是信号的频谱分析,频谱分析最常见的就是FFT,该方法简单易懂,适合电赛时进行学习用来做为信号处理的手段。

  • 5
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C语言中实现FFT算法可以使用以下步骤: 1. 首先,将输入的序列进行码位倒置。这可以通过按位与、或循环实现,或者使用迭代方法进行推导。码位倒置是为了满足FFT的计算特性,以便后续对信号的相关性质进行研究。 2. 接下来,将倒置后的序列进行分组。以N=8为例,可以将序列分为奇偶两组。 3. 对每个分组进行蝶形运算。蝶形运算是FFT算法的核心部分,它将两个输入值进行加法和乘法运算,并输出两个结果。 4. 重复步骤3,直到完成所有的蝶形运算。 5. 最后,将得到的结果按照正常顺序输出,即得到FFT变换后的结果。 需要注意的是,FFT算法可以按照不同的抽取方式进行实现,包括按时间抽取(DIT-FFT)和按频率抽取(DIF-FFT算法。此外,FFT算法还可以根据蝶形运算的构成不同,分为基2、基4、基8和任意因子的类型。 总结起来,C语言实现FFT算法的步骤包括码位倒置、分组、蝶形运算和结果输出。具体的实现可以根据具体的需求和算法类型进行调整。 #### 引用[.reference_title] - *1* [《C》C语言实现FFT算法](https://blog.csdn.net/yga_airspace/article/details/86688278)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [用c语言实现的FFT](https://blog.csdn.net/tf18269639242/article/details/53024276)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值