annotate data/fft/FFTapi.cpp @ 282:d9319859a4cf tip

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