annotate data/fft/FFTapi.cpp @ 263:71dfc6ab3b54

* Threaded mp3/ogg file reading. Not activated yet, as it doesn't work in context (SV needs to know the duration of its main model at the outset)
author Chris Cannam
date Thu, 24 May 2007 16:20:22 +0000
parents e919a2b97c2a
children db946591a391
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@227 22 #include <iostream>
Chris@226 23
Chris@226 24 void
Chris@226 25 fft(unsigned int n, bool inverse, double *ri, double *ii, double *ro, double *io)
Chris@226 26 {
Chris@226 27 if (!ri || !ro || !io) return;
Chris@226 28
Chris@226 29 unsigned int bits;
Chris@226 30 unsigned int i, j, k, m;
Chris@226 31 unsigned int blockSize, blockEnd;
Chris@226 32
Chris@226 33 double tr, ti;
Chris@226 34
Chris@226 35 if (n < 2) return;
Chris@226 36 if (n & (n-1)) return;
Chris@226 37
Chris@226 38 double angle = 2.0 * M_PI;
Chris@226 39 if (inverse) angle = -angle;
Chris@226 40
Chris@226 41 for (i = 0; ; ++i) {
Chris@226 42 if (n & (1 << i)) {
Chris@226 43 bits = i;
Chris@226 44 break;
Chris@226 45 }
Chris@226 46 }
Chris@226 47
Chris@227 48 int *table = new int[n];
Chris@226 49
Chris@227 50 for (i = 0; i < n; ++i) {
Chris@226 51
Chris@227 52 m = i;
Chris@227 53
Chris@227 54 for (j = k = 0; j < bits; ++j) {
Chris@227 55 k = (k << 1) | (m & 1);
Chris@227 56 m >>= 1;
Chris@227 57 }
Chris@227 58
Chris@227 59 table[i] = k;
Chris@226 60 }
Chris@226 61
Chris@226 62 if (ii) {
Chris@226 63 for (i = 0; i < n; ++i) {
Chris@226 64 ro[table[i]] = ri[i];
Chris@226 65 io[table[i]] = ii[i];
Chris@226 66 }
Chris@226 67 } else {
Chris@226 68 for (i = 0; i < n; ++i) {
Chris@226 69 ro[table[i]] = ri[i];
Chris@226 70 io[table[i]] = 0.0;
Chris@226 71 }
Chris@226 72 }
Chris@226 73
Chris@226 74 blockEnd = 1;
Chris@226 75
Chris@226 76 for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
Chris@226 77
Chris@226 78 double delta = angle / (double)blockSize;
Chris@226 79 double sm2 = -sin(-2 * delta);
Chris@226 80 double sm1 = -sin(-delta);
Chris@226 81 double cm2 = cos(-2 * delta);
Chris@226 82 double cm1 = cos(-delta);
Chris@226 83 double w = 2 * cm1;
Chris@226 84 double ar[3], ai[3];
Chris@226 85
Chris@226 86 for (i = 0; i < n; i += blockSize) {
Chris@226 87
Chris@226 88 ar[2] = cm2;
Chris@226 89 ar[1] = cm1;
Chris@226 90
Chris@226 91 ai[2] = sm2;
Chris@226 92 ai[1] = sm1;
Chris@226 93
Chris@226 94 for (j = i, m = 0; m < blockEnd; j++, m++) {
Chris@226 95
Chris@226 96 ar[0] = w * ar[1] - ar[2];
Chris@226 97 ar[2] = ar[1];
Chris@226 98 ar[1] = ar[0];
Chris@226 99
Chris@226 100 ai[0] = w * ai[1] - ai[2];
Chris@226 101 ai[2] = ai[1];
Chris@226 102 ai[1] = ai[0];
Chris@226 103
Chris@226 104 k = j + blockEnd;
Chris@226 105 tr = ar[0] * ro[k] - ai[0] * io[k];
Chris@226 106 ti = ar[0] * io[k] + ai[0] * ro[k];
Chris@226 107
Chris@226 108 ro[k] = ro[j] - tr;
Chris@226 109 io[k] = io[j] - ti;
Chris@226 110
Chris@226 111 ro[j] += tr;
Chris@226 112 io[j] += ti;
Chris@226 113 }
Chris@226 114 }
Chris@226 115
Chris@226 116 blockEnd = blockSize;
Chris@226 117 }
Chris@226 118
Chris@227 119 /* fftw doesn't normalise, so nor will we
Chris@227 120
Chris@226 121 if (inverse) {
Chris@226 122
Chris@226 123 double denom = (double)n;
Chris@226 124
Chris@226 125 for (i = 0; i < n; i++) {
Chris@226 126 ro[i] /= denom;
Chris@226 127 io[i] /= denom;
Chris@226 128 }
Chris@226 129 }
Chris@227 130 */
Chris@227 131 delete[] table;
Chris@226 132 }
Chris@226 133
Chris@226 134 struct fftf_plan_ {
Chris@226 135 int size;
Chris@226 136 int inverse;
Chris@226 137 float *real;
Chris@226 138 fftf_complex *cplx;
Chris@226 139 };
Chris@226 140
Chris@226 141 fftf_plan
Chris@226 142 fftf_plan_dft_r2c_1d(int n, float *in, fftf_complex *out, unsigned)
Chris@226 143 {
Chris@226 144 if (n < 2) return 0;
Chris@226 145 if (n & (n-1)) return 0;
Chris@226 146
Chris@226 147 fftf_plan_ *plan = new fftf_plan_;
Chris@226 148 plan->size = n;
Chris@226 149 plan->inverse = 0;
Chris@226 150 plan->real = in;
Chris@226 151 plan->cplx = out;
Chris@226 152 return plan;
Chris@226 153 }
Chris@226 154
Chris@226 155 fftf_plan
Chris@226 156 fftf_plan_dft_c2r_1d(int n, fftf_complex *in, float *out, unsigned)
Chris@226 157 {
Chris@226 158 if (n < 2) return 0;
Chris@226 159 if (n & (n-1)) return 0;
Chris@226 160
Chris@226 161 fftf_plan_ *plan = new fftf_plan_;
Chris@226 162 plan->size = n;
Chris@226 163 plan->inverse = 1;
Chris@226 164 plan->real = out;
Chris@226 165 plan->cplx = in;
Chris@226 166 return plan;
Chris@226 167 }
Chris@226 168
Chris@226 169 void
Chris@226 170 fftf_destroy_plan(fftf_plan p)
Chris@226 171 {
Chris@226 172 delete p;
Chris@226 173 }
Chris@226 174
Chris@226 175 void
Chris@226 176 fftf_execute(const fftf_plan p)
Chris@226 177 {
Chris@226 178 float *real = p->real;
Chris@226 179 fftf_complex *cplx = p->cplx;
Chris@226 180 int n = p->size;
Chris@227 181 int forward = !p->inverse;
Chris@226 182
Chris@226 183 double *ri = new double[n];
Chris@226 184 double *ro = new double[n];
Chris@226 185 double *io = new double[n];
Chris@226 186
Chris@226 187 double *ii = 0;
Chris@227 188 if (!forward) ii = new double[n];
Chris@226 189
Chris@227 190 if (forward) {
Chris@226 191 for (int i = 0; i < n; ++i) {
Chris@226 192 ri[i] = real[i];
Chris@226 193 }
Chris@226 194 } else {
Chris@226 195 for (int i = 0; i < n/2+1; ++i) {
Chris@226 196 ri[i] = cplx[i][0];
Chris@226 197 ii[i] = cplx[i][1];
Chris@226 198 if (i > 0) {
Chris@226 199 ri[n-i] = ri[i];
Chris@226 200 ii[n-i] = -ii[i];
Chris@226 201 }
Chris@226 202 }
Chris@226 203 }
Chris@226 204
Chris@227 205 fft(n, !forward, ri, ii, ro, io);
Chris@226 206
Chris@227 207 if (forward) {
Chris@226 208 for (int i = 0; i < n/2+1; ++i) {
Chris@226 209 cplx[i][0] = ro[i];
Chris@226 210 cplx[i][1] = io[i];
Chris@226 211 }
Chris@226 212 } else {
Chris@226 213 for (int i = 0; i < n; ++i) {
Chris@226 214 real[i] = ro[i];
Chris@226 215 }
Chris@226 216 }
Chris@226 217
Chris@226 218 delete[] ri;
Chris@226 219 delete[] ro;
Chris@226 220 delete[] io;
Chris@227 221 if (ii) delete[] ii;
Chris@226 222 }
Chris@226 223
Chris@226 224 #endif