音频处理里面常用。 就是把波形(时域信号)变换到频域,使得用户更好的分析。频域就是类似于“千千静听”的频谱。这个过程叫“离散傅立叶变换”(DFT)。而FFT是DFT的一种高效快速算法。
代码见下:
#include <iostream>
#include <stdio.h>
#include <math.h>
//**************************************************************************************
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define DATA_LEN 64
#define SAMPLE_FREQ 1000 // Hz
unsigned char sin_data[64] = {0x7F,0x8B,0x98,0xA4,0xB0,0xBB,0xC6,0xD0,0xD9,0xE2,
0xE9,0xEF,0xF5,0xF9,0xFC,0xFE,0xFE,0xFE,0xFC,0xF9,0xF5,0xEF,0xE9,0xE2,0xD9,0xD0,
0xC6,0xBB,0xB0,0xA4,0x98,0x8B,0x7F,0x73,0x66,0x5A,0x4E,0x43,0x38,0x2E,0x25,0x1C,
0x15,0x0F,0x09,0x05,0x02,0x00,0x00,0x00,0x02,0x05,0x09,0x0F,0x15,0x1C,0x25,0x2E,
0x38,0x43,0x4E,0x5A,0x66,0x73};
typedef struct{
double r;
double i;
} cplx_t;
//**************************************************************************************
void cplx_exp(cplx_t *x, cplx_t *r)
{
double expx = exp(x->r);
r->r = expx*cos(x->i);
r->i = expx*sin(x->i);
}
// 复数乘法
void cplx_mul(cplx_t *x, cplx_t *y, cplx_t *r)
{
r->r = x->r*y->r-x->i*y->i;
r->i = x->r*y->i+x->i*y->r;
}
// 比特反置
void bit_reverse(cplx_t *x, int N)
{
unsigned int i = 0,j = 0,k = 0;
cplx_t tmp;
int bit_num = log(0.0+N)/log(2.0); // 比特位数
for (i=0; i<N; i++)
{
int t = bit_num;
k=i;
j=0;
while (t--)
{
j <<= 1;
j |= k&1;
k >>= 1;
}
if (j>i)
{
tmp = x[i];
x[i] = x[j];
x[j] = tmp;
}
}
}
void fft(cplx_t *x, int N)
{
cplx_t u,d,p,W,tmp;
int i=0,j=0,k=0,l=0;
double M = floor(log(0.0+N)/log(2.0)); // zhiqiu 换底公式
if (log(0.0+N)/log(2.0)-M > 0)
{
printf("The length of x (N) must be a power of two!!!\n");
return;
}
bit_reverse(x,N);
for (i = 0; i < M; i++)
{
l = 1<<i;
for (j = 0; j < N; j += 2*l)
{
for (k = 0; k < l; k++)
{
tmp.r = 0.0;
tmp.i = -2*M_PI*k/2/l;
cplx_exp(&tmp,&W);
cplx_mul(&x[j+k+l],&W,&p);
u.r = x[j+k].r+p.r;
u.i = x[j+k].i+p.i;
d.r = x[j+k].r-p.r;
d.i = x[j+k].i-p.i;
x[j+k] = u;
x[j+k+l] = d;
}
}
}
}
void ifft(cplx_t *x, int N)
{
unsigned int i = 0;
for (i = 0;i < N; i++)
x[i].i = -x[i].i;
fft(x,N);
for (i = 0;i < N; i++)
{
x[i].r = x[i].r/(N+0.0);
x[i].i = -x[i].i/(N+0.0);
}
}
//**************************************************************************************
int main(int argc, const char * argv[])
{
int i;
cplx_t x[DATA_LEN];
for (i=0;i<DATA_LEN;i++)
{
x[i].r = sin_data[i];
x[i].i = 0;
}
printf("Before...\nReal\t\tImag\n");
for (i=0; i<DATA_LEN; i++)
printf("%f\t%f\n",x[i].r,x[i].i);
fft(x, DATA_LEN);
printf("\nAfter FFT...\nReal\t\tImag\n");
for (i=0; i<DATA_LEN; i++)
printf("%f\t%f\n",x[i].r,x[i].i);
printf("\n频率\t\t幅度\t\t相位\n");
for (i=0; i<DATA_LEN; i++)
{
double fudu = sqrt(x[i].r*x[i].r+x[i].i*x[i].i);
double xiangwei = atan(x[i].i/x[i].r)*180.0/M_PI;
if (i == 0)
fudu /= DATA_LEN;
else
fudu /= DATA_LEN/2;
printf("%f\t%f\t%f\n", (double)SAMPLE_FREQ/DATA_LEN*i, fudu, xiangwei);
}
ifft(x, DATA_LEN);
printf("\nAfter IFFT...\nReal\t\tImag\n");
for (i=0; i<DATA_LEN; i++)
printf("%f\t%f\n",x[i].r,x[i].i);
return 0;
}
运行结果:
Before...
Real Imag
127.000000 0.000000
139.000000 0.000000
152.000000 0.000000
164.000000 0.000000
176.000000 0.000000
187.000000 0.000000
198.000000 0.000000
208.000000 0.000000
217.000000 0.000000
226.000000 0.000000
233.000000 0.000000
239.000000 0.000000
245.000000 0.000000
249.000000 0.000000
252.000000 0.000000
254.000000 0.000000
254.000000 0.000000
254.000000 0.000000
252.000000 0.000000
249.000000 0.000000
245.000000 0.000000
239.000000 0.000000
233.000000 0.000000
226.000000 0.000000
217.000000 0.000000
208.000000 0.000000
198.000000 0.000000
187.000000 0.000000
176.000000 0.000000
164.000000 0.000000
152.000000 0.000000
139.000000 0.000000
127.000000 0.000000
115.000000 0.000000
102.000000 0.000000
90.000000 0.000000
78.000000 0.000000
67.000000 0.000000
56.000000 0.000000
46.000000 0.000000
37.000000 0.000000
28.000000 0.000000
21.000000 0.000000
15.000000 0.000000
9.000000 0.000000
5.000000 0.000000
2.000000 0.000000
0.000000 0.000000
0.000000 0.000000
0.000000 0.000000
2.000000 0.000000
5.000000 0.000000
9.000000 0.000000
15.000000 0.000000
21.000000 0.000000
28.000000 0.000000
37.000000 0.000000
46.000000 0.000000
56.000000 0.000000
67.000000 0.000000
78.000000 0.000000
90.000000 0.000000
102.000000 0.000000
115.000000 0.000000
After FFT...
Real Imag
8128.000000 0.000000
0.000000 -4079.961454
0.000000 0.000000
0.000000 -2.073634
0.000000 0.000000
-0.000000 0.912016
0.000000 0.000000
-0.000000 1.409742
0.000000 0.000000
0.000000 1.173062
0.000000 0.000000
0.000000 0.039072
0.000000 0.000000
0.000000 4.791678
0.000000 0.000000
0.000000 0.161168
0.000000 0.000000
0.000000 1.343569
0.000000 0.000000
0.000000 4.934246
0.000000 0.000000
0.000000 1.217879
0.000000 0.000000
0.000000 -3.948687
0.000000 0.000000
-0.000000 6.362596
0.000000 0.000000
0.000000 1.672291
0.000000 0.000000
-0.000000 2.117931
0.000000 0.000000
0.000000 -0.236919
0.000000 0.000000
0.000000 0.236919
0.000000 0.000000
-0.000000 -2.117931
0.000000 0.000000
0.000000 -1.672291
0.000000 0.000000
-0.000000 -6.362596
0.000000 0.000000
-0.000000 3.948687
0.000000 0.000000
0.000000 -1.217879
0.000000 0.000000
-0.000000 -4.934246
0.000000 0.000000
0.000000 -1.343569
0.000000 0.000000
-0.000000 -0.161168
0.000000 0.000000
0.000000 -4.791678
0.000000 0.000000
-0.000000 -0.039072
0.000000 0.000000
0.000000 -1.173062
0.000000 0.000000
-0.000000 -1.409742
0.000000 0.000000
-0.000000 -0.912016
0.000000 0.000000
0.000000 2.073634
0.000000 0.000000
-0.000000 4079.961454
频率 幅度 相位
0.000000 127.000000 0.000000
15.625000 127.498795 -90.000000
31.250000 0.000000 nan
46.875000 0.064801 -90.000000
62.500000 0.000000 nan
78.125000 0.028501 -90.000000
93.750000 0.000000 nan
109.375000 0.044054 -90.000000
125.000000 0.000000 nan
140.625000 0.036658 90.000000
156.250000 0.000000 nan
171.875000 0.001221 90.000000
187.500000 0.000000 nan
203.125000 0.149740 90.000000
218.750000 0.000000 nan
234.375000 0.005036 90.000000
250.000000 0.000000 nan
265.625000 0.041987 90.000000
281.250000 0.000000 nan
296.875000 0.154195 90.000000
312.500000 0.000000 nan
328.125000 0.038059 90.000000
343.750000 0.000000 nan
359.375000 0.123396 -90.000000
375.000000 0.000000 nan
390.625000 0.198831 -90.000000
406.250000 0.000000 nan
421.875000 0.052259 90.000000
437.500000 0.000000 nan
453.125000 0.066185 -90.000000
468.750000 0.000000 nan
484.375000 0.007404 -90.000000
500.000000 0.000000 nan
515.625000 0.007404 90.000000
531.250000 0.000000 nan
546.875000 0.066185 90.000000
562.500000 0.000000 nan
578.125000 0.052259 -90.000000
593.750000 0.000000 nan
609.375000 0.198831 90.000000
625.000000 0.000000 nan
640.625000 0.123396 -90.000000
656.250000 0.000000 nan
671.875000 0.038059 -90.000000
687.500000 0.000000 nan
703.125000 0.154195 90.000000
718.750000 0.000000 nan
734.375000 0.041987 -90.000000
750.000000 0.000000 nan
765.625000 0.005036 90.000000
781.250000 0.000000 nan
796.875000 0.149740 -90.000000
812.500000 0.000000 nan
828.125000 0.001221 90.000000
843.750000 0.000000 nan
859.375000 0.036658 -90.000000
875.000000 0.000000 nan
890.625000 0.044054 90.000000
906.250000 0.000000 nan
921.875000 0.028501 90.000000
937.500000 0.000000 nan
953.125000 0.064801 90.000000
968.750000 0.000000 nan
984.375000 127.498795 -90.000000
After IFFT...
Real Imag
127.000000 -0.000000
139.000000 -0.000000
152.000000 -0.000000
164.000000 -0.000000
176.000000 0.000000
187.000000 -0.000000
198.000000 0.000000
208.000000 -0.000000
217.000000 -0.000000
226.000000 -0.000000
233.000000 0.000000
239.000000 -0.000000
245.000000 -0.000000
249.000000 0.000000
252.000000 0.000000
254.000000 -0.000000
254.000000 -0.000000
254.000000 0.000000
252.000000 0.000000
249.000000 0.000000
245.000000 -0.000000
239.000000 0.000000
233.000000 -0.000000
226.000000 0.000000
217.000000 -0.000000
208.000000 0.000000
198.000000 0.000000
187.000000 0.000000
176.000000 -0.000000
164.000000 0.000000
152.000000 -0.000000
139.000000 0.000000
127.000000 0.000000
115.000000 0.000000
102.000000 0.000000
90.000000 0.000000
78.000000 -0.000000
67.000000 0.000000
56.000000 -0.000000
46.000000 0.000000
37.000000 0.000000
28.000000 0.000000
21.000000 -0.000000
15.000000 0.000000
9.000000 -0.000000
5.000000 -0.000000
2.000000 -0.000000
0.000000 0.000000
0.000000 -0.000000
-0.000000 -0.000000
2.000000 -0.000000
5.000000 -0.000000
9.000000 0.000000
15.000000 -0.000000
21.000000 0.000000
28.000000 -0.000000
37.000000 0.000000
46.000000 -0.000000
56.000000 -0.000000
67.000000 -0.000000
78.000000 0.000000
90.000000 -0.000000
102.000000 0.000000
115.000000 -0.000000