svcore  1.9
FFTapi.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006 Chris Cannam and QMUL.
8  FFT code from Don Cross's public domain FFT implementation.
9 
10  This program is free software; you can redistribute it and/or
11  modify it under the terms of the GNU General Public License as
12  published by the Free Software Foundation; either version 2 of the
13  License, or (at your option) any later version. See the file
14  COPYING included with this distribution for more information.
15 */
16 
17 #include "FFTapi.h"
18 
19 #ifndef HAVE_FFTW3F
20 
21 #include <cmath>
22 #include <iostream>
23 
24 void
25 fft(unsigned int n, bool inverse, double *ri, double *ii, double *ro, double *io)
26 {
27  if (!ri || !ro || !io) return;
28 
29  unsigned int bits;
30  unsigned int i, j, k, m;
31  unsigned int blockSize, blockEnd;
32 
33  double tr, ti;
34 
35  if (n < 2) return;
36  if (n & (n-1)) return;
37 
38  double angle = 2.0 * M_PI;
39  if (inverse) angle = -angle;
40 
41  for (i = 0; ; ++i) {
42  if (n & (1 << i)) {
43  bits = i;
44  break;
45  }
46  }
47 
48  int *table = new int[n];
49 
50  for (i = 0; i < n; ++i) {
51 
52  m = i;
53 
54  for (j = k = 0; j < bits; ++j) {
55  k = (k << 1) | (m & 1);
56  m >>= 1;
57  }
58 
59  table[i] = k;
60  }
61 
62  if (ii) {
63  for (i = 0; i < n; ++i) {
64  ro[table[i]] = ri[i];
65  io[table[i]] = ii[i];
66  }
67  } else {
68  for (i = 0; i < n; ++i) {
69  ro[table[i]] = ri[i];
70  io[table[i]] = 0.0;
71  }
72  }
73 
74  blockEnd = 1;
75 
76  for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
77 
78  double delta = angle / (double)blockSize;
79  double sm2 = -sin(-2 * delta);
80  double sm1 = -sin(-delta);
81  double cm2 = cos(-2 * delta);
82  double cm1 = cos(-delta);
83  double w = 2 * cm1;
84  double ar[3], ai[3];
85 
86  for (i = 0; i < n; i += blockSize) {
87 
88  ar[2] = cm2;
89  ar[1] = cm1;
90 
91  ai[2] = sm2;
92  ai[1] = sm1;
93 
94  for (j = i, m = 0; m < blockEnd; j++, m++) {
95 
96  ar[0] = w * ar[1] - ar[2];
97  ar[2] = ar[1];
98  ar[1] = ar[0];
99 
100  ai[0] = w * ai[1] - ai[2];
101  ai[2] = ai[1];
102  ai[1] = ai[0];
103 
104  k = j + blockEnd;
105  tr = ar[0] * ro[k] - ai[0] * io[k];
106  ti = ar[0] * io[k] + ai[0] * ro[k];
107 
108  ro[k] = ro[j] - tr;
109  io[k] = io[j] - ti;
110 
111  ro[j] += tr;
112  io[j] += ti;
113  }
114  }
115 
116  blockEnd = blockSize;
117  }
118 
119 /* fftw doesn't normalise, so nor will we
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  delete[] table;
132 }
133 
134 struct fftf_plan_ {
135  int size;
136  int inverse;
137  float *real;
138  fftf_complex *cplx;
139 };
140 
141 fftf_plan
142 fftf_plan_dft_r2c_1d(int n, float *in, fftf_complex *out, unsigned)
143 {
144  if (n < 2) return 0;
145  if (n & (n-1)) return 0;
146 
147  fftf_plan_ *plan = new fftf_plan_;
148  plan->size = n;
149  plan->inverse = 0;
150  plan->real = in;
151  plan->cplx = out;
152  return plan;
153 }
154 
155 fftf_plan
156 fftf_plan_dft_c2r_1d(int n, fftf_complex *in, float *out, unsigned)
157 {
158  if (n < 2) return 0;
159  if (n & (n-1)) return 0;
160 
161  fftf_plan_ *plan = new fftf_plan_;
162  plan->size = n;
163  plan->inverse = 1;
164  plan->real = out;
165  plan->cplx = in;
166  return plan;
167 }
168 
169 void
171 {
172  delete p;
173 }
174 
175 void
176 fftf_execute(const fftf_plan p)
177 {
178  float *real = p->real;
179  fftf_complex *cplx = p->cplx;
180  int n = p->size;
181  int forward = !p->inverse;
182 
183  double *ri = new double[n];
184  double *ro = new double[n];
185  double *io = new double[n];
186 
187  double *ii = 0;
188  if (!forward) ii = new double[n];
189 
190  if (forward) {
191  for (int i = 0; i < n; ++i) {
192  ri[i] = real[i];
193  }
194  } else {
195  for (int i = 0; i < n/2+1; ++i) {
196  ri[i] = cplx[i][0];
197  ii[i] = cplx[i][1];
198  if (i > 0) {
199  ri[n-i] = ri[i];
200  ii[n-i] = -ii[i];
201  }
202  }
203  }
204 
205  fft(n, !forward, ri, ii, ro, io);
206 
207  if (forward) {
208  for (int i = 0; i < n/2+1; ++i) {
209  cplx[i][0] = ro[i];
210  cplx[i][1] = io[i];
211  }
212  } else {
213  for (int i = 0; i < n; ++i) {
214  real[i] = ro[i];
215  }
216  }
217 
218  delete[] ri;
219  delete[] ro;
220  delete[] io;
221  if (ii) delete[] ii;
222 }
223 
224 #endif
#define fftf_destroy_plan
Definition: FFTapi.h:30
#define fftf_plan
Definition: FFTapi.h:26
#define fftf_plan_dft_c2r_1d
Definition: FFTapi.h:28
#define fftf_execute
Definition: FFTapi.h:29
#define fftf_plan_dft_r2c_1d
Definition: FFTapi.h:27
#define fftf_complex
Definition: FFTapi.h:23