在Linux平台下,从音频接口采回PCM数据,进行FFT变换。最后通过ncurse库,在文本模式下粗糙得对频谱进行实时显示。
整个程序只是作为练手用,代码贴在下面,供自己查阅和大家参考。
Makefile
all: directshow.o fft.o gcc -o spectrum directshow.o fft.o -lm -lcurses directshow.o: directshow.c fft.h gcc -c directshow.c fft.o: fft.c gcc -c fft.c
fft.c
/******************************************************************************* * File: fft.c * Author: Jerome Wang * wangquzhi@gmail.com * Last Edit: 2011/01/19 * Description: void fft(double *DataTimeDomain_r, double *DataTimeDomain_i); * Basic funtion used for fft. Two parameters, for the real-part and j-part * of the input data. The results are also restored here. * Chose the point of fft by define one of these macros: * FFT_CONFIG_4 * FFT_CONFIG_8 * FFT_CONFIG_128 * * By define FFT_DEBUGE, we can get the debug message indicating the process * of the fft processing. *******************************************************************************/ #include <math.h> #include <stdio.h> #define FFT_CONFIG_128 /*#define FFT_DEBUGE*/ #define PI 3.14 inline void Butterfly(double *a_r, double *a_i, \ double *b_r, double * b_i,\ double wx, int N) { double a_tmp_r = *a_r; double a_tmp_i = *a_i; double b_tmp_r = *b_r; double b_tmp_i = *b_i; double wx_tmp_r, wx_tmp_i; wx_tmp_r = cos(wx*2*PI/N); wx_tmp_i = -sin(wx*2*PI/N); *a_r = a_tmp_r + b_tmp_r*wx_tmp_r - b_tmp_i*wx_tmp_i; *a_i = a_tmp_i + b_tmp_r*wx_tmp_i + b_tmp_i*wx_tmp_r; *b_r = a_tmp_r - b_tmp_r*wx_tmp_r + b_tmp_i*wx_tmp_i; *b_i = a_tmp_i - b_tmp_r*wx_tmp_i - b_tmp_i*wx_tmp_r; } inline int BitReverse(int n, int bits) { int i = 0; int ret = 0; for(i = 0; i < bits; i++) { ret|=((n>>i)&1)<<(bits-i-1); } return ret; } void fft(double *DataTimeDomain_r, double *DataTimeDomain_i) { #ifdef FFT_CONFIG_128 const int FFT_Pnt = 128; /* For 2^7 = 128, 128 points' computation is divided to 7 stages */ const int FFT_Stg = 7; /* In each stage, it contains BttrPerStg butterfly computations */ const int BttrPerStg = 64; #endif #ifdef FFT_CONFIG_8 const int FFT_Pnt = 8; const int FFT_Stg = 3; const int BttrPerStg = 4; #endif #ifdef FFT_CONFIG_4 const int FFT_Pnt = 4; const int FFT_Stg = 2; const int BttrPerStg = 2; #endif /* Current Computing Stage, ranges from 0 to (FFT_Stg - 1) */ int CrrtStg = 0; /* Current Butterfly, ranges from 0 to (BttrPerStg - 1) */ int CrrtBttr = 0; int TempPower = 0; int BttrPara1 = 0; int BttrPara2 = 0; int BttrPara3 = 0; for(CrrtStg = 0; CrrtStg < FFT_Stg; CrrtStg++) { #ifdef FFT_DEBUGE printf("This is the %dnd Stage:\n", CrrtStg+1); #endif for(CrrtBttr = 0; CrrtBttr < BttrPerStg; CrrtBttr++) { TempPower = 1 << CrrtStg; BttrPara1 = (CrrtBttr/TempPower)*(TempPower<<1)+CrrtBttr%TempPower; BttrPara2 = BttrPara1 + TempPower; BttrPara3 = (CrrtBttr % TempPower) * \ (1 << (BttrPerStg - CrrtStg - 1)) >> 1; #ifdef FFT_DEBUGE printf("\tNow we perform the butterfly: %d,%d,%d\n", \ BitReverse(BttrPara1, FFT_Stg),\ BitReverse(BttrPara2, FFT_Stg),\ BttrPara3); #endif Butterfly(DataTimeDomain_r + BitReverse(BttrPara1, FFT_Stg),\ DataTimeDomain_i + BitReverse(BttrPara1, FFT_Stg),\ DataTimeDomain_r + BitReverse(BttrPara2, FFT_Stg),\ DataTimeDomain_i + BitReverse(BttrPara2, FFT_Stg),\ BttrPara3,\ FFT_Pnt); } } }
fft.h