找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1520|回复: 0
收起左侧

C语言写的FFT代码

[复制链接]
ID:996634 发表于 2021-12-26 17:19 | 显示全部楼层 |阅读模式
/*   新手上路还望见谅。  *
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <stdlib.h>

  4. #define   N     8     //64  输入样本总数
  5. #define    M     3   //DFT运算层数     //2^m=N  
  6. #define    PI    3.1415926

  7. float   twiddle[N/2] = {1.0, 0.707, 0.0, -0.707};
  8. float   x_r[N] = {1, 1, 1, 1, 0, 0, 0, 0};  //输入数据,此处设为8个
  9. float   x_i[N];                         //N=8


  10. /**
  11. * 初始化输出虚部
  12. */
  13. static void fft_init( void )
  14. {
  15.     int i;
  16.     for(i=0; i<N; i++)   x_i[i] = 0.0;
  17. }

  18. /**
  19. * 反转算法.将时域信号重新排序.
  20. * 这个算法有改进的空间
  21. */
  22. static void bitrev( void )
  23. {
  24.     int    p=1, q, i;
  25.     int    bit_rev[ N ];  
  26.     float   xx_r[ N ];   
  27.    
  28.     bit_rev[ 0 ] = 0;
  29.     while( p < N )
  30.     {
  31.        for(q=0; q<p; q++)  
  32.        {
  33.            bit_rev[ q ]     = bit_rev[ q ] * 2;
  34.            bit_rev[ q + p ] = bit_rev[ q ] + 1;
  35.        }
  36.        p *= 2;
  37.     }
  38.    
  39.     for(i=0; i<N; i++)   xx_r[ i ] = x_r[ i ];   
  40.    
  41.     for(i=0; i<N; i++)   x_r[i] = xx_r[ bit_rev[i] ];
  42. }

  43. void fft( void )
  44. {   fp = fopen("log2.txt", "a+");//此处
  45.     int     cur_layer, gr_num, i, k, p;        //cur_layer代表正要计算的当前层,gr_num代表当前层的颗粒数
  46.     float   tmp_real, tmp_imag, temp;   // 临时变量, 记录实部
  47.     float   tw1, tw2;// 旋转因子,tw1为旋转因子的实部cos部分, tw2为旋转因子的虚部sin部分.
  48.       
  49.     int    step;      // 步进
  50.     int    sample_num;   // 颗粒的样本总数(各层不同, 因为各层颗粒的输入不同)
  51.    
  52.     /* 对层循环 */
  53.     for(cur_layer=1; cur_layer<=M; cur_layer++)
  54.     {      
  55.        /* 求当前层拥有多少个颗粒(gr_num) */
  56.        gr_num = 1;
  57.        i = M - cur_layer;
  58.        while(i > 0)
  59.        {
  60.            i--;
  61.            gr_num *= 2;
  62.        }
  63.       
  64.        /* 每个颗粒的输入样本数N' */
  65.        sample_num    = (int)pow(2, cur_layer);
  66.        /* 步进. 步进是N'/2 */
  67.        step       = sample_num/2;
  68.       
  69.        /*  */
  70.        k = 0;
  71.       
  72.        /* 对颗粒进行循环 */
  73.        for(i=0; i<gr_num; i++)
  74.        {
  75.            /*
  76.             * 对样本点进行循环, 注意上限和步进
  77.             */
  78.            for(p=0; p<sample_num/2; p++)
  79.            {   
  80.               // 旋转因子, 需要优化...   
  81.               tw1 = cos(2*PI*p/pow(2, cur_layer));
  82.               tw2 = -sin(2*PI*p/pow(2, cur_layer));
  83.               
  84.               tmp_real = x_r[k+p];
  85.               tmp_imag = x_i[k+p];
  86.               temp = x_r[k+p+step];
  87.               
  88.               /* 蝶形算法 */
  89.               x_r[k+p]   = tmp_real + ( tw1*x_r[k+p+step] - tw2*x_i[k+p+step] );
  90.               x_i[k+p]   = tmp_imag + ( tw2*x_r[k+p+step] + tw1*x_i[k+p+step] );
  91.               /* X[k] = A(k)+WB(k)
  92.                * X[k+N/2] = A(k)-WB(k) 的性质可以优化这里*/
  93.               /*旋转因子, 需要优化...
  94.               tw1 = cos(2*PI*(p+step)/pow(2, cur_layer));
  95.               tw2 = -sin(2*PI*(p+step)/pow(2, cur_layer));
  96.               x_r[k+p+step] = tmp_real + ( tw1*temp - tw2*x_i[k+p+step] );
  97.               x_i[k+p+step] = tmp_imag + ( tw2*temp + tw1*x_i[k+p+step] );*/
  98.         x_r[k+p+step]   = tmp_real - ( tw1* temp - tw2*x_i[k+p+step] );
  99.               x_i[k+p+step]   = tmp_imag - ( tw2* temp + tw1*x_i[k+p+step] );
  100.               
  101.               printf("k=%d, x_r[k]=%f, x_i[k]=%f\n", k+p, x_r[k+p], x_i[k+p]);
  102.               printf("k=%d, x_r[k]=%f, x_i[k]=%f\n", k+p+step, x_r[k+p+step], x_i[k+p+step]);
  103.            }
  104.            /* 开跳!:) */
  105.            k += 2*step;
  106.        }   
  107.     }
  108. }

  109. void display( void )
  110. {
  111.     printf("\n\n");
  112.     int   i;  
  113.     for(i=0; i<N; i++)
  114.        printf("%f\t%f\n", x_r[i], x_i[i]);
  115. }

  116. int main( void )
  117. {
  118.     fft_init( );                //初始化
  119.     bitrev( );                //将输入直接按FFT计算要求排序,如8点FFT计算,排序为x[0]、x[4]、x[2]、x[6]、x[1]、x[5]、x[3]、x[7]
  120.     fft( );                        //进行FFT计算
  121.     display( );                //显示计算结果
  122.    
  123.     system( "pause" );
  124.     return 1;
  125. }

复制代码

评分

参与人数 1黑币 +10 收起 理由
admin + 10 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表