fft库函数的用法以及C与DSP编程中的区别

文章属于原创内容,引用需注明出处!(尊重原创力量,人人做起)
另外,感觉有用就点个赞吧。

一、序

前几天已经简单介绍过DSP中fft变换函数的用法,具体可以参考DSPF_sp_fftSPxSP_r2c函数的用法
在从VS的C++©工程向DSP的CCS工程移植时,发现同样是做fft变换,却有很多细微之处存在显著差异。下面就举例对比下:

二、实例对比

  1. C:
	fftw_complex *in, *out;
	in = (fftw_complex*)fftw_malloc(FFTWCOMPLEXLEN*len);
	out = (fftw_complex*)fftw_malloc(FFTWCOMPLEXLEN*len);
	if (in == NULL || out == NULL)
	{
		if (in != NULL) fftw_free(in);
		if (out != NULL) fftw_free(out);
		return -1;
	}
	// fft
	fftw_plan pfft = fftw_plan_dft_1d(len, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
	for (int i = 0; i<len; i++)
	{
		in[i][0] = radiated_noise[i]; in[i][1] = 0;
	}
	fftw_execute(pfft);
	// 1/(t*fs)频带带宽级0dB的白噪声乘以对应连续谱理想幅频响应
	for (int i = 0; i<len; i++)
	{
		out[i][0] = *(pamp_fre + i) * out[i][0] * sqrt(t*fs);
		out[i][1] = *(pamp_fre + i) * out[i][1] * sqrt(t*fs);
	}
	// ifft
	pfft = fftw_plan_dft_1d(len, out, in, FFTW_BACKWARD, FFTW_ESTIMATE);
	fftw_execute(pfft);
	for (int i = 0; i<len; i++)
		radiated_noise[i] = in[i][0] / len;

	fftw_destroy_plan(pfft);
	fftw_free(in);
	fftw_free(out);
  1. DSP
	float Input[2 * len];
//	float InputOrig[2 * len];
	float FFT_Out[2 * len];
	float IFFT_Out[2 * len];
	// 旋转因子
	//#pragma DATA_ALIGN(W, 8);
	float W[2 * len];

	// 二进制位翻转
	//#pragma DATA_ALIGN (brev, 8);  	// 8字节对齐
	unsigned char brev[64] =
	{
		0x00, 0x20, 0x10, 0x30, 0x08, 0x28, 0x18, 0x38,
		0x04, 0x24, 0x14, 0x34, 0x0c, 0x2c, 0x1c, 0x3c,
		0x02, 0x22, 0x12, 0x32, 0x0a, 0x2a, 0x1a, 0x3a,
		0x06, 0x26, 0x16, 0x36, 0x0e, 0x2e, 0x1e, 0x3e,
		0x01, 0x21, 0x11, 0x31, 0x09, 0x29, 0x19, 0x39,
		0x05, 0x25, 0x15, 0x35, 0x0d, 0x2d, 0x1d, 0x3d,
		0x03, 0x23, 0x13, 0x33, 0x0b, 0x2b, 0x1b, 0x3b,
		0x07, 0x27, 0x17, 0x37, 0x0f, 0x2f, 0x1f, 0x3f
	};

	// 基
	unsigned char rad;
	if(len == 64 || len == 256 || len == 1024 || len == 4096 || len == 16384 || len == 65536)
	{
		rad = 4;
	}
	else if(len == 32 || len == 128 || len == 512 || len == 2048 || len == 8192 || len == 32768)
	{
		rad = 2;
	}
	else
	{
		printf ("不支持计算 %d 点快速傅里叶变换!\n", len);

		while(1);
	}

	for (i = 0; i < len; i++)
		{
			Input[i] = radiated_noise[i];
		}

	// 产生旋转因子
	tw_gen(W, len);

	// FFT 计算
	DSPF_sp_fftSPxSP_r2c(len, Input, W, FFT_Out, brev, rad, 0, len);

	for ( i = 0; i<len; i++)
	{
		FFT_Out[2*i] = *(pamp_fre + i) * FFT_Out[2 * i]* sqrt(t*fs);
		FFT_Out[2*i + 1] = *(pamp_fre + i) * FFT_Out[ 2 * i + 1] * sqrt(t*fs);
	}

	// 产生旋转因子
	tw_geni(W, len);

	// IFFT 计算
	DSPF_sp_ifftSPxSP_c2r(len, FFT_Out, W, IFFT_Out, brev, rad, 0, len);

	for ( i = 0; i<len; i++)
		radiated_noise[i] = IFFT_Out[i] ;	//  DSP不用除以数据长度len

三、总结

根据实例对比,两种编程方式有以下几点差异:
1.fft变换所需要的输入输出变量类型不同,VS中需要借住"fftw3.h"这个库函数中的fftw_complex 类型来定义函数所需要的变量;
(关于fftw3.h库函数的安装使用主要注意:将libfftw3-3.lib在VS里添加为依赖项(项目>属性>Configuration Properities>Linker>Input>Additional Dependencies>编辑输入libfftw3-3.lib),同时把libfftw3-3.dll放在生成.exe的文件夹下, 另在也需要把libfftw3-3.lib和fftw3.h两个文件放在VS工程目录下,不然的话需要添加其路径((项目>属性>Configuration Properities>VC++ Directories>添加Executable\Include\Library Directories)。
2.函数名不一样,VS中的fft函数名以及用法和CUDA编程十分相似,记忆里完全一样;
3.函数所需要使用变量的长度不一样。假如要计算的数据长度为N,VS中使用的fftw_complex 变量一般是个二维变量,长度(列数)也为N,宽度(行数)为2。无论是正fft还是逆fft,第一行为实部,第二行是虚部;CCS中直接使用长度为2N的变量即可。在fft变换中,前N代表信号,在逆fft变换中,偶数位是实部,奇数位是虚部。
4.VS中fft逆变换结果需要除以数据长度N,DSP不需要。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值