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