花了几天时间实现了一下TI的C64系列DSPLib实现fft,结果基本还行,也有一些需要改进的地方。先总结一下。
该系列的DSPLib可以在ti的官网上下载到。把其中的examples目录下的fft_example.c例程稍微修改了一下,实现复数的FFT运算。代码很简单,如下:
/* ======================================================================= */
/* fft_example.c -- FFT Example File */
/* */
/* Rev 0.0.1 */
/* */
/* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ */
/* */
/* */
/* Redistribution and use in source and binary forms, with or without */
/* modification, are permitted provided that the following conditions */
/* are met: */
/* */
/* Redistributions of source code must retain the above copyright */
/* notice, this list of conditions and the following disclaimer. */
/* */
/* Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in the */
/* documentation and/or other materials provided with the */
/* distribution. */
/* */
/* Neither the name of Texas Instruments Incorporated nor the names of */
/* its contributors may be used to endorse or promote products derived */
/* from this software without specific prior written permission. */
/* */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* */
/* This example demonstrates the usage of the various FFT kernels */
/* provided with the C6x DSPLIB. The example shows: */
/* - Twiddle factor generation for the various kernels */
/* - Scaling that needs to be applied to get similar output */
/* when using different kernels */
/* - Demonstrates the usage of FFT APIs */
/* */
/* ----------------------------------------------------------------------- */
/* Copyright (c) 2011 Texas Instruments, Incorporated. */
/* All Rights Reserved. */
/* ======================================================================= */
//#define _TMS320C6400_PLUS
#include <stdint.h>
#include <math.h>
#include <ti/dsplib/dsplib.h>
#include "gen_twiddle_fft16x16.h"
#include "gen_twiddle_fft16x32.h"
#include "gen_twiddle_fft32x32.h"
/* Global definitions */
/* Number of samples for which FFT needs to be calculated */
#define N 512
/* Align the tables that we have to use */
#pragma DATA_ALIGN(x_32x32, 8);
int32_t x_32x32[2 * N];
#pragma DATA_ALIGN(y_32x32, 8);
int32_t y_32x32[2 * N];
#pragma DATA_ALIGN(w_32x32, 8);
int32_t w_32x32[2 * N];
/*
This function generates the input data and also updates the
input data arrays used by the various FFT kernels
*/
float x_ref_float[2 * N];
int32_t y_abs_32x32[N];
void generateInput(int32_t numSinWaves) {
int32_t i, j;
/* Clear the input floating point array */
for (i = 0; i < N; i++) {
x_ref_float[2 * i] = (float) 0.0;
x_ref_float[2 * i + 1] = (float) 0.0;
}
for (j = 0; j < numSinWaves; j++) {
for (i = 0; i < N; i++) {
x_ref_float[2 * i] = (float) cos(
2 * 3.1415926 * 100 * (j + 1) / 1000 * i)
+ 1 * (float) cos(2 * 3.1415926 * 30 * (j + 1) / 1000 * i);
x_ref_float[2 * i + 1] = (float) sin(
2 * 3.1415926 * 100 * (j + 1) / 1000 * i)
+ 1 * (float) sin(2 * 3.1415926 * 30 * (j + 1) / 1000 * i);
}
}
/* Convert the floating point data to reference fixed point data */
for (i = 0; i < N; i++) {
x_32x32[2 * i] = (int32_t) (x_ref_float[2 * i] * 1024);
x_32x32[2 * i + 1] = (int32_t) (x_ref_float[2 * i + 1] * 1024);
}
}
seperateRealImg() {
int i;
for (i = 0; i < N; i++) {
y_abs_32x32[i] = (int32_t) sqrt(
(double) (y_32x32[2 * i]) * (double) (y_32x32[2 * i])
+ (double) (y_32x32[2 * i + 1])
* (double) (y_32x32[2 * i + 1]));
}
}
/*
The main function that implements the example functionality.
This example demonstrates the usage of the various FFT kernels provided
with the C6x DSPLIB. The example shows:
- Twiddle factor generation for the various kernels
- Needed scaling to get correct output
- Demonstrates usage of FFT APIs
*/
void main() {
/* Generate the input data */
generateInput(1);
/* Genarate the various twiddle factors */
gen_twiddle_fft32x32(w_32x32, N, 2147483647.5);
/* Call the various FFT routines */
DSP_fft32x32_cn(w_32x32, N, x_32x32, y_32x32);
/* Call the test code to seperate the real and imaginary data */
seperateRealImg();
while (1)
;
}
/* ======================================================================== */
/* End of file: fft_example.c */
/* ------------------------------------------------------------------------ */
/* Copyright (c) 2011 Texas Instruments, Incorporated. */
/* All Rights Reserved. */
/* ======================================================================== */
效果如下图:
总结一下:
1.用了两个复数单频信号(解析信号,没有负频率),频率分别为30和100,采样频率为1000.用graph显示基本正确(好像偏了一个分辨率?)。图里面显示的是x_32x32。
2.浮点转整型没有用例程的方法,简单乘以了1024,有些简陋(输入信号幅值为-2到2的小数)。
3.模值y_abs_32x32的结果看着不错,可惜在graph中未看到能调节x轴尺度的参数,所以y_abs_32x32的显示的频率位置要比正确的频率位置小一半。
4.FFT的运行速度真快,前面函数的运行速度真慢。