Tony小周 2024-04-19 14:56 采纳率: 83.3%
浏览 4
已结题

解读以下代码解读以下代码

解读以下代码,解释一下percent的作用是干嘛的


void fft(const unsigned short arr[], unsigned int allfre_info[][2], unsigned int Fs, int num, int percent)
{
#define PI 3.14159265358979323846
    int NUM = 1 << num;               // 根据输入参数num计算FFT的长度,即FFT点数。
    float *XI = (float *)testsram; // 定义两个浮点型数组,分别用于存储实部和虚部。这里使用了共享内存testsram,XR存储实部,XI存储虚部。
    float *XR = (float *)(testsram + NUM * 4);
    int i, j, k;
    for (i = 0; i < 50; i++)//初始化置零 这是存储峰值信息的
    {
        allfre_info[i][0] = 0;
        allfre_info[i][1] = 0;
    }
    for (i = 0; i < NUM; i++) 
    {
        XR[i] = (float)arr[i];
        //        printf("%d,", arr[i]);
    }

    for (i = 0; i < NUM; i++)
    {
        k = 0;
        for (j = 0; j < num; j++)
        {
            if (((i >> j) & 0x01) == 1)
                k = k + (1 << (num - j - 1));
        }
        XI[k] = XR[i];
    }

    for (i = 0; i < NUM; i++)
    {
        XR[i] = XI[i];
    }

    int TR, TI, WR, WI;
    for (int i = 0; i < num; i++)
    {
        int B = 1 << i;
        for (int j = 0; j < B; j++)
        {
            int p = j * (1 << (num - i - 1)); // //旋转因子的系数
            for (int k = j; k < NUM; k = k + 2 * B)
            {
                TR = XR[k];
                TI = XI[k];

                WR = XR[k + B] * FFT_COS_13[p] + XI[k + B] * FFT_COS_13[(p + (NUM / 4))]; // 旋转因子是有虚部的 
                WI = -XR[k + B] * FFT_COS_13[(p + (NUM / 4))] + XI[k + B] * FFT_COS_13[p];

                //                printf("p = %d  %lf  %lf  %d\n\r", p, cos( (2*PI*p)/NUM ), FFT_COS_13[p], (cos( (2*PI*p)/NUM ) == FFT_COS_13[p]));
                //                WR= XR[k+B]*cos((2*PI*p)/NUM)+XI[k+B]*sin((2*PI*p)/NUM);//旋转因子是有虚部的 
                //                WI=-XR[k+B]*sin((2*PI*p)/NUM)+XI[k+B]*cos((2*PI*p)/NUM);

                XR[k] = (TR + WR);
                XI[k] = TI + WI;
                XR[k + B] = (TR - WR);
                XI[k + B] = TI - WI;
            }
        }
    }

    for (i = 0; i < NUM; i++)
    {
        XR[i] = sqrt((XR[i] * XR[i]) + (XI[i] * XI[i]));//求模
    }

    {
        float max = 0;
        int index = 0;
        float old_max;
        for (int i = 1; i < NUM / 2; i++)//寻找最大值
        {
            index = (max > XR[i]) ? index : i;
            max = (max > XR[i]) ? max : XR[i];
        }
        //    printf("\n\n");
        //    for(int i = 1; i < NUM / 2; i++)
        //        printf("%d,", (int)XR[i]);
        //    printf("\n\n");
        for (int i = 1; i < NUM / 2; i++)

            XR[i] = XR[i] - max / percent;
        old_max = max;
        max = 1;
        allfre_info[0][0] = 1;
        allfre_info[0][1] = XR[0]; // / (NUM * pow(2, 0.5));
        for (int index = 1, info_index = 1, edge_state = 0; index < NUM / 2; index++)//寻峰算法 代码的主要目的是计算特定频率范围内的能量谱,并在循环过程中更新最大值和边缘状态。
        {
            if (XR[index] > 0)
            {
                if (XR[index] >= max)
                {
                    max = XR[index];
                    edge_state = 1;
                }
                else if (XR[index] < max && edge_state == 1)
                {    //索引位置的信息存储到allfre_info数组中某点n所表示的频率为:fn=(n-1)*fs/N
                    allfre_info[info_index][0] = (index - 1) * (float)Fs / NUM;
                    //                allfre_info[info_index][0] = (index);
                    allfre_info[info_index][1] = old_max / percent + XR[index - 1];
                    for (int i = 0; i < 1; i++)
                    {
                        if (index - 2 - i > 0)
                            allfre_info[info_index][1] += 2 * old_max / percent + XR[index + i] + XR[index - 2 - i];
                    }
                    allfre_info[info_index][1] = allfre_info[info_index][1] / (NUM / 2);//归一化幅值
                    info_index++;
                    edge_state = 0;
                }
            }
            else
            {
                if (edge_state)
                {
                    allfre_info[info_index][0] = (index - 1) * (float)Fs / NUM;
                    //                allfre_info[info_index][0] = (index);
                    allfre_info[info_index][1] = ((3 * old_max / percent) + XR[index] + max + XR[index - 2]) / (NUM / 2);
                    info_index++;
                    edge_state = 0;
                }
                max = 1;
                if (info_index >= 49)
                {
                    break;
                }
            }
        }
        // printf("allfre_info[1][0] = %d\n\r", allfre_info[1][0]);
        //        if(allfre_info[1][0] <= 320 && Fs == 25000) {
        //            return;
        //        }
        //        printf("\n\r\n\r");
        //double SUM = 0;
        //int a[50] = {0};
        for (int i = 1; i < 50; i++)
        {
            if (allfre_info[i][0])
            {
                //                printf(" Fre = %d  vpp = %d \n\r", allfre_info[i][0], allfre_info[i][1]);
                //                SUM += allfre_info[i][1] * abs(((int)allfre_info[i][0] - 100048) / 300);
                //                a[i - 1] = allfre_info[i][1];
            }
            else
            {
                //                printf(" i = %d SUM = %f\n\r", i, SUM);
                //                allfre_info[0][1] = (u32)SUM;
                //                printf(" avg = %d\n\r", avg(a, i - 1, allfre_info[0][1] / (i - 1)));
                //                printf(" Fre = %d\n\r", allfre_info[i][0] - allfre_info[i - 1][0]);
                //                printf(" mf = %f\n\r", (float)(allfre_info[i][0] - allfre_info[1][0]) / 2 / (float)(allfre_info[i][0] - allfre_info[i - 1][0]) );
                return;
            }
        }
    }
}
  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-19 14:56
    关注

    引自免费微信小程序:皆我百晓生

    这段C语言代码实现了一个快速傅立叶变换(FFT)算法,并在此基础上进行了一些后续处理,主要目标是计算特定频率范围内的能量谱,并且通过一个名为percent的参数调整结果。

    首先,我们来看看percent的作用。在函数中,percent参数被用来调整信号幅度。具体来说,在代码的后半部分,有一段处理fft结果的逻辑,这部分负责查找峰值并计算其对应的频率以及幅度。当找到一个新的峰值时,会将其与前一个峰值的幅度进行加权平均,权重由percent决定。这可以理解为一种平滑处理,使得最终的结果对幅度变化更加敏感或不敏感,取决于percent的大小。较小的percent值会使结果更敏感于幅度的变化,而较大的percent值则会使结果更加稳定,减少小幅度波动的影响。

    下面是整个函数的逐行解释:

    1. 函数定义:void fft(const unsigned short arr[], unsigned int allfre_info[][2], unsigned int Fs, int num, int percent) 输入参数:
      • arr[]: 待处理的一维实数信号数组
      • allfre_info[][]: 存储频率和幅度信息的二维数组,格式为 [frequency, amplitude]
      • Fs: 采样率
      • num: 用于计算FFT长度的二进制位数
      • percent: 平滑处理的比例

    2-3. 宏定义:PI 的值

    1. 计算FFT长度:NUM = 1 << num;

    5-6. 分配共享内存:XIXR 分别存储复数的实部和虚部

    7-10. 初始化 allfre_info 数组

    11-13. 将输入信号 arr 的数据复制到 XR

    14-17. 重新排列 XR 中的数据,准备执行FFT

    18-21. 将排列后的数据从 XI 转回 XR

    22-41. 快速傅立叶变换(FFT)的核心部分,采用的是蝶形结构,通过嵌套循环完成

    42-45. 对每个FFT结果取模,得到频域中的复数幅度

    46-105. 处理FFT结果,寻找峰值、计算频率和幅度,并将结果存入 allfre_info 数组,同时考虑percent的平滑效果

    106-109. 结束处理,返回或根据条件退出

    在这段代码中,percent 参数决定了计算新的峰值幅度时,新旧峰值之间的加权平均程度。例如,如果 percent 为 100,则意味着完全依赖新的峰值幅度;如果 percent 为 0,则始终使用旧的峰值幅度。实际应用中,可以通过调整这个参数来控制输出结果的灵敏度。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 4月28日
  • 已采纳回答 4月20日
  • 创建了问题 4月19日

悬赏问题

  • ¥15 winFrom界面无法打开
  • ¥15 crossover21 ARM64版本安装软件问题
  • ¥15 mymetaobjecthandler没有进入
  • ¥15 mmo能不能做客户端怪物
  • ¥15 osm下载到arcgis出错
  • ¥15 Dell g15 每次打开eiq portal后3分钟内自动退出
  • ¥200 使用python编写程序,采用socket方式获取网页实时刷新的数据,能定时print()出来就行。
  • ¥15 matlab如何根据图片中的公式绘制e和v的曲线图
  • ¥15 我想用Python(Django)+Vue搭建一个用户登录界面,但是在运行npm run serve时报错了如何解决?
  • ¥15 QQ邮箱过期怎么恢复?