文章属于原创内容,引用需注明出处!(尊重原创力量,人人做起)
另外,感觉有用就点个赞吧。
一、序
前几天已经简单介绍过DSP中fft变换函数的用法,具体可以参考DSPF_sp_fftSPxSP_r2c函数的用法
在从VS的C++©工程向DSP的CCS工程移植时,发现同样是做fft变换,却有很多细微之处存在显著差异。下面就举例对比下:
二、实例对比
- 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);
- 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不需要。