FFTW的使用方法 - 实数输入的数字滤波示例


前言

本文主要记录FFTW的安装过程,FFTW的简单示例代码。并实现一个输入和输出为一维实数的数字滤波器

FFT的一些理论知识可以参考:
从头到尾彻底理解傅里叶变换算法
傅里叶分析之掐死教程(完整版)

一、滤波效果

先展示效果。如图一为滤波前后时域波形对比,经过低通滤波后,波形变的比较平滑。
滤波前后时域波形对比
滤除了10kHz以上的高频,以下为滤波前后频域波形对比。
原始频谱
低通滤波后的频谱
接下来是使用FFTW使用滤波的具体步骤。


二、下载、安装FFTW

FFTW官网下载源码 http://www.fftw.org/download.html
在这里插入图片描述

我是用在linux系统下,下载tar包,并解压

tar -zxvf ./fftw-3.3.10.tar.gz
cd ./fftw-3.3.10/

进行安装。一般使用默认配置安装即可(默认不使能多线程库、实数为double类型),只需如下3步
若要定制化修改配置可参考官方的 配置说明文档

./configure
make
make install

默认会安装到 /usr/local 路径下,其中 /usr/local/include放置头文件,/usr/local/lib放置.a文件

FFTW安装完成,可直接在编译时链接。


三、 FFTW简单示例代码

一维复数的FFT及IFFT

贴上官方给出的示例,IFFT的只需把fftw_plan_dft_1d()函数的FFTW_FORWARD改为FFTW_BACKWARD

#include <fftw3.h>
...
{
    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);
    ...
    fftw_execute(p); /* repeat as needed */
    ...
    fftw_destroy_plan(p);
    fftw_free(in); fftw_free(out);
}

一维实数的FFT及IFFT

一维实数的FFT和IFFT写在一起,为了更好理解功能。实际上转换前后的数据基本(近似)相同

#include <fftw3.h>
void fft_real_f(int n, const float *in, float *out)
{
    int i, begin, end;
    double *real;
    fftw_complex *complex;
    fftw_plan plan;

    // fftw的内存分配方式和mallco类似,但使用SIMD(单指令多数据流)时,fftw_alloc会将数组以更高效的方式对齐
    real = fftw_alloc_real(n);
    complex = fftw_alloc_complex(n/2+1);    // 实际只会用到(n/2)+1个complex对象

    // Step1:FFT实现时域到频域的转换
    plan = fftw_plan_dft_r2c_1d(n, real, complex, FFTW_ESTIMATE);
    for (i = 0; i < n; i++)
    {
        real[i] = in[i];
    }

    // 对长度为n的实数进行FFT,输出的长度为(n/2)-1的复数
    fftw_execute(plan);
    fftw_destroy_plan(plan);

    // Step3:IFFT实现频域到时域的转换
    // 使用FFTW_ESTIMATE构建plan不会破坏输入数据
    plan = fftw_plan_dft_c2r_1d(n, complex, real, FFTW_ESTIMATE);

    fftw_execute(plan);
    fftw_destroy_plan(plan);

    for (i = 0; i < n; i++)
    {
        // 需除以数据个数,得到滤波后的实数
        out[i] = real[i] / n;
    }

    fftw_free(real);
    fftw_free(complex);
}

GCC编译

使用GCC编译是命令如下

gcc fft.c -lfftw3 -lm

四. 实现数字滤波器

接下来是实际FFT的应用,实现一个数字滤波器

/**
 * @Description : 使用FFT进行滤波
 *                使用示例:
 *                  原始采样频率为100kHz,采集了10000个点,保存为单精度浮点数。滤除其中20kHz~30kHz的频率
 *                  fft_filter_f(10000, in, out, 100e3, 20e3, 30e3)
 * @Input       : n             输入数据个数
 *                in            输入数据
 *                              in和out指向不同位置,不改变输入
 *                              in和out指向相同位置,输出将覆盖输入
 *                sample_rate   原始数据采样频率 Hz
 *                freq_start    需过滤的起始频率 Hz
 *                freq_end      需过滤的截止频率 Hz
 *                              若freq_end大于采样频率的50%,则将滤除大于freq_start的所有高频信号
 * @Output      : out           输出数据
 *                              in和out指向不同位置,不改变输入
 *                              in和out指向相同位置,输出将覆盖输入
 * @Return      : 无
*/
void fft_filter_f(int n, const float *in, float *out, float sample_rate, float freq_start, float freq_end)
{
    int i, begin, end;
    double *real;
    fftw_complex *complex;
    fftw_plan plan;

    // fftw的内存分配方式和mallco类似,但使用SIMD(单指令多数据流)时,fftw_alloc会将数组以更高效的方式对齐
    real = fftw_alloc_real(n);
    complex = fftw_alloc_complex(n/2+1);    // 实际只会用到(n/2)+1个complex对象

    // Step1:FFT实现时域到频域的转换
    plan = fftw_plan_dft_r2c_1d(n, real, complex, FFTW_ESTIMATE);
    for (i = 0; i < n; i++)
    {
        real[i] = in[i];
    }

    // 对长度为n的实数进行FFT,输出的长度为(n/2)-1的复数
    fftw_execute(plan);
    fftw_destroy_plan(plan);

    // Step2:计算需滤波的频率在频域数组中的下标
    begin = (int)((freq_start / sample_rate) * n);
    end = (int)((freq_end / sample_rate) * n);
    end = end < (n / 2 + 1) ? end : (n / 2 + 1);
    for (i = begin; i < end; i++)
    {
        // 对应的频率分量置为0,即去除该频率
        complex[i][0] = 0;
        complex[i][1] = 0;
    }
    
    // Step3:IFFT实现频域到时域的转换
    // 使用FFTW_ESTIMATE构建plan不会破坏输入数据
    plan = fftw_plan_dft_c2r_1d(n, complex, real, FFTW_ESTIMATE);

    fftw_execute(plan);
    fftw_destroy_plan(plan);

    // Step4:计算滤波后的时域值
    for (i = 0; i < n; i++)
    {
        // 需除以数据个数,得到滤波后的实数
        out[i] = real[i] / n;
    }

    fftw_free(real);
    fftw_free(complex);
}

  • 8
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
fftw-3.3.5-dll32是一个软件包的名称,这个软件包是FFTW(快速分布式变换库)的一个特定版本。FFTW是一个用于执行多种类型快速傅里叶变换(FFT)的软件库,它提供了一系列高效的算法和函数。 在fftw-3.3.5-dll32中,"dll32"表示这个软件包提供了32位操作系统的动态链接库(Dynamic Link Library),这意味着它可以在32位的Windows操作系统上使用。动态链接库是一种重用代码的方式,它允许多个程序使用同一个库文件而不需要重复编写相同的代码,从而节省了磁盘空间和内存的消耗。 fftw-3.3.5-dll32这个软件包提供了一系列函数和工具,可以在32位Windows操作系统上进行快速傅里叶变换的计算。它的设计旨在提供高性能、可移植性和易于使用。可以使用它来执行一维、二维和三维的FFT计算,适用于各种应用领域,如信号处理、图像处理、数据压缩等。 要使用fftw-3.3.5-dll32,首先需要从官方网站或其他可靠来源下载并安装这个软件包。安装完成后,可以在自己的程序中引用相应的函数和库文件,然后使用这些函数进行FFT计算。具体的使用方法可以参考官方提供的文档或示例代码。 总之,fftw-3.3.5-dll32是一个用于在32位Windows操作系统上执行快速傅里叶变换计算的软件包,它提供了方便、高效且易于使用的函数和工具,可以在信号处理、图像处理等领域中应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值