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