Mercurial > hg > devuvuzelator
comparison fft.cpp @ 9:a1539d4e3b08
* Tidy code, start doc
author | Chris Cannam |
---|---|
date | Sat, 12 Jun 2010 13:08:33 +0100 |
parents | |
children | 1e6360396b6c |
comparison
equal
deleted
inserted
replaced
8:e15ebd222c63 | 9:a1539d4e3b08 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 #ifdef VST | |
4 #include "devuvuzelator-vst.h" | |
5 #else | |
6 #ifdef LADSPA | |
7 #include "devuvuzelator-ladspa.h" | |
8 #else | |
9 #error Need to define either VST or LADSPA | |
10 #endif | |
11 #endif | |
12 | |
13 // FFT implementation by Don Cross, public domain. | |
14 // This version scales the forward transform. | |
15 | |
16 void Devuvuzelator::fft(unsigned int n, bool inverse, | |
17 double *ri, double *ii, double *ro, double *io) | |
18 { | |
19 if (!ri || !ro || !io) return; | |
20 | |
21 unsigned int bits; | |
22 unsigned int i, j, k, m; | |
23 unsigned int blockSize, blockEnd; | |
24 | |
25 double tr, ti; | |
26 | |
27 if (n < 2) return; | |
28 if (n & (n-1)) return; | |
29 | |
30 double angle = 2.0 * M_PI; | |
31 if (inverse) angle = -angle; | |
32 | |
33 for (i = 0; ; ++i) { | |
34 if (n & (1 << i)) { | |
35 bits = i; | |
36 break; | |
37 } | |
38 } | |
39 | |
40 static unsigned int tableSize = 0; | |
41 static int *table = 0; | |
42 | |
43 if (tableSize != n) { | |
44 | |
45 delete[] table; | |
46 | |
47 table = new int[n]; | |
48 | |
49 for (i = 0; i < n; ++i) { | |
50 | |
51 m = i; | |
52 | |
53 for (j = k = 0; j < bits; ++j) { | |
54 k = (k << 1) | (m & 1); | |
55 m >>= 1; | |
56 } | |
57 | |
58 table[i] = k; | |
59 } | |
60 | |
61 tableSize = n; | |
62 } | |
63 | |
64 if (ii) { | |
65 for (i = 0; i < n; ++i) { | |
66 ro[table[i]] = ri[i]; | |
67 io[table[i]] = ii[i]; | |
68 } | |
69 } else { | |
70 for (i = 0; i < n; ++i) { | |
71 ro[table[i]] = ri[i]; | |
72 io[table[i]] = 0.0; | |
73 } | |
74 } | |
75 | |
76 blockEnd = 1; | |
77 | |
78 for (blockSize = 2; blockSize <= n; blockSize <<= 1) { | |
79 | |
80 double delta = angle / (double)blockSize; | |
81 double sm2 = -sin(-2 * delta); | |
82 double sm1 = -sin(-delta); | |
83 double cm2 = cos(-2 * delta); | |
84 double cm1 = cos(-delta); | |
85 double w = 2 * cm1; | |
86 double ar[3], ai[3]; | |
87 | |
88 for (i = 0; i < n; i += blockSize) { | |
89 | |
90 ar[2] = cm2; | |
91 ar[1] = cm1; | |
92 | |
93 ai[2] = sm2; | |
94 ai[1] = sm1; | |
95 | |
96 for (j = i, m = 0; m < blockEnd; j++, m++) { | |
97 | |
98 ar[0] = w * ar[1] - ar[2]; | |
99 ar[2] = ar[1]; | |
100 ar[1] = ar[0]; | |
101 | |
102 ai[0] = w * ai[1] - ai[2]; | |
103 ai[2] = ai[1]; | |
104 ai[1] = ai[0]; | |
105 | |
106 k = j + blockEnd; | |
107 tr = ar[0] * ro[k] - ai[0] * io[k]; | |
108 ti = ar[0] * io[k] + ai[0] * ro[k]; | |
109 | |
110 ro[k] = ro[j] - tr; | |
111 io[k] = io[j] - ti; | |
112 | |
113 ro[j] += tr; | |
114 io[j] += ti; | |
115 } | |
116 } | |
117 | |
118 blockEnd = blockSize; | |
119 } | |
120 | |
121 if (!inverse) { | |
122 | |
123 double denom = (double)n; | |
124 | |
125 for (i = 0; i < n; i++) { | |
126 ro[i] /= denom; | |
127 io[i] /= denom; | |
128 } | |
129 } | |
130 } | |
131 |