annotate data/fft/FFTapi.cpp @ 301:73537d900d4b

* Add MIDI file export (closes FR#1643721)
author Chris Cannam
date Thu, 04 Oct 2007 11:52:38 +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