annotate data/fft/FFTapi.cpp @ 226:a867be73b638

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