annotate data/fft/FFTapi.cpp @ 1184:e5a1d815f331 3.0-integration

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