QT中使用fftw库

开发环境:

系统:Windows 10

QT版本:5.10

编译器:mingw32

 

1.下载fftw

http://www.fftw.org/install/windows.html,根据自已编译器版本下载32位或64位

2.生成lib库

使用visual studio里面的lib.exe工具(已管理员权限运行CMD),进入fftw-3.3.5-dll32目录,运行:

lib /def:libfftw3-3.def
lib /def:libfftw3f-3.def
lib /def:libfftw3l-3.def

会生成对应的lib和exp文件,如果需要.a库文件,把.lib直接重命名为.a即可

 

3.qt工程设置

在pro文件中添加lib和头文件

将libfftw3-3.dll,libfftw3f-3.dll和libfftw3l-3.dll拷贝到工程的build目录下

 

4.测试

读一个48K,16bit,单声道的pcm文件,然后通过fft变换后显示振幅谱和相位谱。

/**
 * @brief MainWindow::show_amplitude_waveform 显示频域的幅度
 * @param file_path 数据文件
 * @param polt_1    显示振幅
 * @param polt_2    显示相位
 * @return
 */
int MainWindow::show_amplitude_waveform(char * file_path, QCustomPlot *polt_1, QCustomPlot *polt_2)
{
    double val_max = 0;
    size_t result;
    char  *buf;
    short *in_buf;
    FILE *fp1=fopen(file_path, "rb");   //打开读权限
    fseek(fp1,0,SEEK_END);  //文件指针从0挪到尾部
    long filesize;
    filesize=ftell(fp1);    //ftell求文件指针相对于0的便宜字节数,就求出了文件字节数
    int N = filesize/2;     //计算数据个数

    if(fp1==NULL)   //判断文件是否打开
    {
        QMessageBox::critical(NULL, "错误", "\"" + QString(QLatin1String(file_path)) + "\"" + "文件打开失败!", QMessageBox::Yes, QMessageBox::Yes);
        return -1;
    }

    rewind(fp1);    //还原指针位置
    buf=(char *)malloc(filesize);   //开辟空间给缓存数组
    if(buf==NULL)
    {
        QMessageBox::critical(NULL, "错误", "\"" + QString(QLatin1String(file_path)) + "\"" + "内存分配失败!", QMessageBox::Yes, QMessageBox::Yes);
        return -1;
    }

    result =fread(buf, 1, filesize, fp1);//每次读一个字节到buf,同时求读的次数
    if(result != filesize)  //判断读的次数和文件大小是否一致
    {
        QMessageBox::critical(NULL, "错误", "\"" + QString(QLatin1String(file_path)) + "\"" + "文件读取失败!", QMessageBox::Yes, QMessageBox::Yes);
        return -1;
    }

    in_buf = (short *)buf;  //强转为short,因为采样深度是16bit

    //为fft输入计算分配空间
    double * in = (double*)fftw_malloc(sizeof(double) * N);
    for(int i=0; i<N; i++)
    {
        in[i] = in_buf[i];  //将pcm文件中的数据复制到fft的输入
    }

    //为fft输出算分配空间
    fftw_complex * out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * N);

    //进行fft变换,fftw_plan_dft_c2r_1d函数进行反变换
    fftw_plan p = FFTW3_H::fftw_plan_dft_r2c_1d(N, in, out, FFTW_ESTIMATE);
    fftw_execute(p);

    double dx3 = (double)SAMPLE_RATE / N;

    polt_1->xAxis->setRange(0, SAMPLE_RATE/2, Qt::AlignLeft);

    //根据FFT计算的复数计算振幅谱
    for( int i=0; i<N/2; i++ )
    {
        double val = sqrt(out[i][0] * out[i][0] + out[i][1] * out[i][1]);
        val = val / (N / 2);
        polt_1->graph(0)->addData( dx3 * i, val );

        if( val > val_max )
        {
            val_max = val;
        }

        double db = log(val);
        //qDebug("frequency = %f, amplitude = %f, db = %f", dx3 * i, val / (N / 2), db);
    }

    polt_1->yAxis->setRange(val_max*0.6, val_max*1.2, Qt::AlignBottom);
    polt_1->replot();

    polt_2->xAxis->setRange(0, SAMPLE_RATE/2, Qt::AlignLeft);
    polt_2->yAxis->setRange(0, 10, Qt::AlignBaseline);
    //根据FFT计算的复数计算相位谱
    for( int i=0; i<N/2; i++ )
    {
        double val = atan2(out[i][1], out[i][0]);
        polt_2->graph(0)->addData( dx3 * i, val );
    }
    polt_2->replot();

    fclose(fp1);    //关闭文件指针
    fftw_destroy_plan(p);
    free(buf);      //释放buf
    fftw_free(in);
    fftw_free(out);

    return 0;
}

 

  • 11
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值