annotate data/fft/FFTapi.cpp @ 1188:d9698ee93659 spectrogram-minor-refactor

Extend column logic to peak frequency display as well, and correct some scopes according to whether values are per source column or per target pixel
author Chris Cannam
date Mon, 20 Jun 2016 12:00:32 +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