fftw的使用

news/2025/3/15 21:45:11/

1、下载编译

官网:http://www.fftw.org/index.html

2、FFT基础知识

2.1 概念

  • FFT分辨率可以表示为:fs/Nfft
    频率分辨率的物理量就是:观测信号的时间窗长度, 时间窗越长(N大), 对应频率分辨率就越高。
    提高频率分辨率的两种方法:增加fft点数N(计算量大),降低采样率(时间分辨率降低了)。

  • 输出取N/2个频点,N点fft的输出值也是N个(对称的),故只取一半。

  • 时域上的补0相当于频域上的插值,通过补0增加的fft点数无法提高fft精度

  • 幅度、相位

  • 示例:fs =1024/10 N=1024 △f=0.1Hz

2.2 对1024个点的信号,做4次256点FFT和1次1024点FFT的区别

有信号如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

如果拆分成4个4点FFT,或者1个16点,其中的数学关系不能凭直觉发现,但是,如果把这段信号拆分成:

1 2 3 4 | 0 0 0 0 | 0  0  0  0 | 0  0  0  0
0 0 0 0 | 5 6 7 8 | 0  0  0  0 | 0  0  0  0
0 0 0 0 | 0 0 0 0 | 9 10 11 12 | 0  0  0  0
0 0 0 0 | 0 0 0 0 | 0  0  0  0 |13 14 15 16

然后做4次16点的FFT,那么这4次16点的FFT频谱叠加,最后得到的叠加后的频谱就=一次16点的FFT.
那么,问题就变成了: 1个带12个0的16点的FFT1个4点的FFT之间是什么关系?
1 2 3 4 0 0 0 0 0 0 0 0 0 0 0 0和1 2 3 4,他们的频谱,就相当于1234的4点频谱做插值成16个点.
至于0 0 0 0 5 6 7 8 0 0 0 0 0 0 0 0和5 6 7 8 之间的关系,你知道根据时移定理,对频谱乘一个e^-i2pikm相当于时域上延迟k个点:0 0 0 0 5 6 7 8 0 0 0 0 0 0 0 0可以变形为5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0
也就是说,4点4FFT与1点的16FFT的关系,大致相当于:

FFT(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)=插值(FFT(1,2,3,4))+插值(FFT(5,6,7,8))*时移+插值(FFT(9,10,11,12))*时移^2+插值(FFT(13,14,15,16))*时移^3

3、FFTW基础

3.1 基本函数

plan= fftw_plan_dft_1d(_N,_in,_out,FFTW_BACKWARD,FFTW_MEASURE);//配置计算计划
倒数第二个参数sign, FFTW_FORWARD:正变换 ;FFTW_BACKWARD:逆变换。
最后的一个参数flags,FFTW_MEASURE:表示先计算一些FFT并测量所用的时间,以便为大小为n的变换寻找最优的计算方法。//c-c
fftw_plan fftw_plan_dft_1d(int n, fftw_complex *in, fftw_complex *out, int sign, unsigned flags);
fftw_plan fftw_plan_dft_2d(int n0, int n1, fftw_complex *in, fftw_complex *out, int sign, unsigned flags);
fftw_plan fftw_plan_dft_3d(int n0, int n1, int n2, fftw_complex *in, fftw_complex *out, int sign, unsigned flags);
fftw_plan fftw_plan_dft(int rank, const int *n, fftw_complex *in, fftw_complex *out, int sign, unsigned flags);
//r-c
fftw_plan fftw_plan_dft_r2c_1d(int n, double *in, fftw_complex *out, unsigned flags);
fftw_plan fftw_plan_dft_r2c_2d(int n0, int n1, double *in, fftw_complex *out, unsigned flags);
fftw_plan fftw_plan_dft_r2c_3d(int n0, int n1, int n2, double *in, fftw_complex *out, unsigned flags);
fftw_plan fftw_plan_dft_r2c(int rank, const int *n, double *in, fftw_complex *out, unsigned flags);
//r-r
fftw_plan fftw_plan_r2r_1d(int n, double *in, double *out, fftw_r2r_kind kind, unsigned flags);
fftw_plan fftw_plan_r2r_2d(int n0, int n1, double *in, double *out, fftw_r2r_kind kind0, fftw_r2r_kind kind1, unsigned flags);
fftw_plan fftw_plan_r2r_3d(int n0, int n1, int n2, double *in, double *out, fftw_r2r_kind kind0, fftw_r2r_kind kind1, fftw_r2r_kind kind2, unsigned flags);
fftw_plan fftw_plan_r2r(int rank, const int *n, double *in, double *out, const fftw_r2r_kind *kind, unsigned flags);
void fftw_execute(const fftw_plan p);
void fftw_execute_dft(const fftw_plan p, fftw_complex *in, fftw_complex *out);     
void fftw_execute_split_dft(const fftw_plan p, double *ri, double *ii, double *ro, double *io);     
void fftw_execute_dft_r2c(const fftw_plan p,double *in, fftw_complex *out);     
void fftw_execute_split_dft_r2c(const fftw_plan p, double *in, double *ro, double *io);
void fftw_execute_dft_c2r(const fftw_plan p, fftw_complex *in, double *out);
void fftw_execute_split_dft_c2r(const fftw_plan p, double *ri, double *ii, double *out);
void fftw_execute_r2r(const fftw_plan p, double *in, double *out);

单序列正反变换的归一化处理时:除以N/2

3.2数据类型

FFTW有三个版本的数据类型:double、float、long double,
使用方法如下:

  • 链接对应的库(比如libfftw3-3、libfftw3f-3、或ibfftw3l-3) 包含同样的头文件fftw3.h
    单精度 前缀 “-fftwf” 编译选项 “-lfftw3f”
    双精度 前缀 “-fftwl” 编译选项 “-lfftw3l”
  • 将所有以小写"fftw_“开头的名字替换为"fftwf_”(float版本)或"fftwl_"(long double版本)。
    比如将fftw_complex替换为fftwf_complex,
    将fftw_execute替换为fftwf_execute等。
  • 所有以大写"FFTW_"开头的名字不变,将函数参数中的double替换为float或long double

最后,虽然long double是C99的标准,但你的编译器可能根本不支持该类型,或它并不能提供比double更高的精度。

3、示例

Qt中用fftw对音频数据变换
全球最快的傅里叶变换算法(FFTW)

#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); 				// 执行变换...fftw_destroy_plan(p);fftw_free(in); fftw_free(out);
}

音频变换的例子:

	int N = filesize/2;     			//计算数据个数short *in_buf;						//自己存输入数据//为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();//根据FFT计算的复数计算相位谱polt_2->xAxis->setRange(0, SAMPLE_RATE/2, Qt::AlignLeft);polt_2->yAxis->setRange(0, 10, Qt::AlignBaseline);	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();//fftw销毁fftw_destroy_plan(p);	fftw_free(in);fftw_free(out);

N点的FFT,以 “采样率/N” 为频率间隔,


http://www.ppmy.cn/news/92855.html

相关文章

Chat-GPT 聚合平台 Poe:集成多个 AI 聊天机器人

Chat-GPT 聚合平台 Poe&#xff1a;集成多个 AI 聊天机器人 介绍 Poe 是知名问答社区 Quora 推出的 AI 平台——开放探索平台 (Platform for Open Exploration, Poe)。Poe 集成了多个基于大型语言模型的聊天机器人&#xff0c;包括 ChatGPT&#xff0c;以及 Sage、Claude、Dr…

典型的高可用设计(二):MySQL

一、高可用模式 MySQL数据库提供了数据库建的复制能力&#xff0c;做到了多个数据库同时拥有同一个数据副本&#xff0c;保证了数据的安全性&#xff0c;一台数据库服务器出现问题&#xff0c;其他数据库可以做到数据不丢失。MySQL的服务高可用设计也是以数据库复制能力为基础&…

Kotlin

高阶函数 高阶函数是将函数用作参数或返回值的函数,还可以把函数赋值给一个变量。 所有函数类型都有一个圆括号括起来的参数类型列表以及一个返回类型&#xff1a;(A, B) -> C 表示接受类型分别为 A 与 B 两个参数并返回一个 C 类型值的函数类型。 参数类型列表可以为空&a…

AI怎么把游戏变好玩?米哈游出手了

《原神》发布两年半后&#xff0c;游戏新贵米哈游终于出新&#xff0c;上线了《崩坏:星穹铁道》。新游戏的一大亮点是内置了一个“图生图”的AIGC工具&#xff0c;用户可上传任何图片&#xff0c;生成对应风格的游戏角色“三月七”。 广大玩家脑洞大开&#xff0c;短短一周时间…

解决方案: MySQL JSON字段匹配值忽略大小写不敏感匹配结果

问题背景 MySQL 5.7 数据库由于历史原因设置的字符集为utf8 &#xff0c;排序规则为utf8_general_ci , 表是新建的&#xff0c;默认字符集设置为ut8mb4,排序规则为 ut8mb4_general_ci, utf8_bin/utf8mb4&#xff1a;将字符串中的每一个字符以十六进制方式存储数据&#xff0c…

Python之网络编程

一、操作系统基础 操作系统&#xff1a;&#xff08;Operating System&#xff0c;简称OS&#xff09;是管理和控制计算机硬件与软件资源的计算机程序&#xff0c;是直接运行在“裸机”上的最基本的系统软件&#xff0c;任何其他软件都必须在操作系统的支持下才能运行。 注&a…

GPU云服务器Stable Diffusion搭建保姆级教程

搭建Stable Diffusion最大门槛就是GPU。许多人的电脑配置太低&#xff0c;根本无法搭建。或者即使搭建出来&#xff0c;但是跑图太慢。说多了不通过&#xff0c;看下图。 选择服务器 我选择的是境外GPU服务器&#xff0c;windows版本&#xff08;73.59元&#xff09;。linux会…

python 内置模块multiprocessing,进程

一、简介 进程是操作系统进行资源分配的基本单位&#xff0c;也就是说每启动一个进程&#xff0c;操作系统都会给其分配一定的运行资源(内存资源)保证进程的运行&#xff1b;每个进程都是独立运行的&#xff0c;不互相干扰 注意&#xff1a;&#xff1a;进程锁和线程锁大同小异…