annotate dmfft.c @ 749:44138892c784

Add FFT routines.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 04 May 2013 23:29:22 +0300
parents
children e6d807ce715b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
749
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
1 /*
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
2 * Realfftf
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
3 * Originally (C) Copyright 1993 Philib Van Baren
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
4 * Cleaned up and refactored to be re-entrant by
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
5 * Matti 'ccr' Hamalainen <ccr@tnsp.org>, 2013
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
6 *
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
7 * Note: Output is BIT-REVERSED! so you must use the BitReversed to
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
8 * get legible output, (i.e. Real_i = buffer[ BitReversed[i] ]
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
9 * Imag_i = buffer[ BitReversed[i]+1 ] )
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
10 * Input is in normal order.
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
11 */
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
12 #include "dmfft.h"
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
13 #include <math.h>
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
14
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
15
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
16 int dmInitializeFFT(DMFFTContext * ctx, const int fftlen)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
17 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
18 int i;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
19
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
20 if (ctx == NULL)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
21 return DMERR_NULLPTR;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
22
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
23 if (fftlen <= 16)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
24 return DMERR_INVALID_ARGS;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
25
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
26 // Allocate necessary tables
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
27 ctx->npoints = fftlen / 2;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
28 ctx->sinTable = (DMFFTType *) dmMalloc(fftlen * sizeof(DMFFTType));
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
29 if (ctx->sinTable == NULL)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
30 return DMERR_MALLOC;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
31
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
32 // Bitreversion buffer
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
33 ctx->breversed = (int *) dmMalloc(ctx->npoints * sizeof(int));
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
34 if (ctx->breversed == NULL)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
35 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
36 dmFree(ctx->sinTable);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
37 return DMERR_MALLOC;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
38 }
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
39
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
40 // Calculate data
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
41 for (i = 0; i < ctx->npoints; i++)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
42 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
43 int mask, tmp;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
44 for (tmp = 0, mask = ctx->npoints / 2; mask > 0; mask >>= 1)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
45 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
46 tmp = (tmp >> 1) + ((i & mask) ? ctx->npoints : 0);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
47 }
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
48
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
49 ctx->breversed[i] = tmp;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
50 }
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
51
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
52 for (i = 0; i < ctx->npoints; i++)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
53 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
54 ctx->sinTable[ctx->breversed[i]] = -sin((2.0f * M_PI * i) / fftlen);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
55 ctx->sinTable[ctx->breversed[i] + 1] =
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
56 -cos((2.0f * M_PI * i) / fftlen);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
57 }
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
58
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
59 return DMERR_OK;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
60 }
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
61
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
62
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
63 void dmEndFFT(DMFFTContext * ctx)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
64 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
65 if (ctx != NULL)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
66 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
67 dmFree(ctx->breversed);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
68 dmFree(ctx->sinTable);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
69 memset(ctx, 0, sizeof(DMFFTContext));
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
70 }
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
71 }
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
72
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
73
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
74 int dmRealFFT(DMFFTContext * ctx, DMFFTType * buffer)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
75 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
76 if (ctx == NULL || buffer == NULL)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
77 return DMERR_NULLPTR;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
78
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
79 int rounds = ctx->npoints / 2;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
80 DMFFTType *endptr1 = buffer + ctx->npoints * 2;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
81
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
82 while (rounds > 0)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
83 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
84 DMFFTType *sptr = ctx->sinTable;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
85 DMFFTType *A = buffer,
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
86 *B = buffer + rounds * 2;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
87
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
88 while (A < endptr1)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
89 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
90 DMFFTType qsin = *sptr;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
91 DMFFTType qcos = *(sptr + 1);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
92 DMFFTType *endptr2 = B;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
93
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
94 while (A < endptr2)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
95 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
96 DMFFTType v1 = (*B) * qcos + (*(B + 1)) * qsin;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
97 DMFFTType v2 = (*B) * qsin - (*(B + 1)) * qcos;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
98 *B = (*A + v1) * 0.5;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
99 *(A++) = *(B++) - v1;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
100 *B = (*A - v2) * 0.5;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
101 *(A++) = *(B++) + v2;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
102 }
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
103 A = B;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
104 B += rounds * 2;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
105 sptr += 2;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
106 }
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
107
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
108 rounds >>= 1;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
109 }
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
110
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
111 /*
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
112 * Massage output to get the output for a real input sequence.
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
113 */
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
114 int *br1 = ctx->breversed + 1;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
115 int *br2 = ctx->breversed + ctx->npoints - 1;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
116
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
117 while (br1 <= br2)
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
118 {
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
119 const DMFFTType vsin = ctx->sinTable[*br1];
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
120 const DMFFTType vcos = ctx->sinTable[*br1 + 1];
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
121 DMFFTType *A = buffer + *br1,
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
122 *B = buffer + *br2,
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
123 HRplus, HRminus,
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
124 HIplus, HIminus,
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
125 tmp1, tmp2;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
126
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
127 HRminus = *A - *B;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
128 HRplus = HRminus + (*B * 2);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
129
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
130 HIminus = *(A + 1) - *(B + 1);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
131 HIplus = HIminus + (*(B + 1) * 2);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
132
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
133 tmp1 = (vsin * HRminus) - (vcos * HIplus);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
134 tmp2 = (vcos * HRminus) + (vsin * HIplus);
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
135
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
136 *A = (HRplus + tmp1) * 0.5f;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
137 *B = *A - tmp1;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
138
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
139 *(A + 1) = (HIminus + tmp2) * 0.5f;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
140 *(B + 1) = (*(A + 1)) - HIminus;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
141
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
142 br1++;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
143 br2--;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
144 }
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
145
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
146 // Handle DC bin separately
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
147 buffer[0] += buffer[1];
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
148 buffer[1] = 0;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
149
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
150 return DMERR_OK;
44138892c784 Add FFT routines.
Matti Hamalainen <ccr@tnsp.org>
parents:
diff changeset
151 }