Chris@9: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@9: Chris@13: #define _USE_MATH_DEFINES Chris@13: #include Chris@13: Chris@9: #ifdef VST Chris@9: #include "devuvuzelator-vst.h" Chris@9: #else Chris@9: #ifdef LADSPA Chris@9: #include "devuvuzelator-ladspa.h" Chris@9: #else Chris@9: #error Need to define either VST or LADSPA Chris@9: #endif Chris@9: #endif Chris@9: Chris@9: // FFT implementation by Don Cross, public domain. Chris@9: // This version scales the forward transform. Chris@9: Chris@9: void Devuvuzelator::fft(unsigned int n, bool inverse, Chris@9: double *ri, double *ii, double *ro, double *io) Chris@9: { Chris@9: if (!ri || !ro || !io) return; Chris@9: Chris@9: unsigned int bits; Chris@9: unsigned int i, j, k, m; Chris@9: unsigned int blockSize, blockEnd; Chris@9: Chris@9: double tr, ti; Chris@9: Chris@9: if (n < 2) return; Chris@9: if (n & (n-1)) return; Chris@9: Chris@9: double angle = 2.0 * M_PI; Chris@9: if (inverse) angle = -angle; Chris@9: Chris@9: for (i = 0; ; ++i) { Chris@9: if (n & (1 << i)) { Chris@9: bits = i; Chris@9: break; Chris@9: } Chris@9: } Chris@9: Chris@9: static unsigned int tableSize = 0; Chris@9: static int *table = 0; Chris@9: Chris@9: if (tableSize != n) { Chris@9: Chris@9: delete[] table; Chris@9: Chris@9: table = new int[n]; Chris@9: Chris@9: for (i = 0; i < n; ++i) { Chris@9: Chris@9: m = i; Chris@9: Chris@9: for (j = k = 0; j < bits; ++j) { Chris@9: k = (k << 1) | (m & 1); Chris@9: m >>= 1; Chris@9: } Chris@9: Chris@9: table[i] = k; Chris@9: } Chris@9: Chris@9: tableSize = n; Chris@9: } Chris@9: Chris@9: if (ii) { Chris@9: for (i = 0; i < n; ++i) { Chris@9: ro[table[i]] = ri[i]; Chris@9: io[table[i]] = ii[i]; Chris@9: } Chris@9: } else { Chris@9: for (i = 0; i < n; ++i) { Chris@9: ro[table[i]] = ri[i]; Chris@9: io[table[i]] = 0.0; Chris@9: } Chris@9: } Chris@9: Chris@9: blockEnd = 1; Chris@9: Chris@9: for (blockSize = 2; blockSize <= n; blockSize <<= 1) { Chris@9: Chris@9: double delta = angle / (double)blockSize; Chris@9: double sm2 = -sin(-2 * delta); Chris@9: double sm1 = -sin(-delta); Chris@9: double cm2 = cos(-2 * delta); Chris@9: double cm1 = cos(-delta); Chris@9: double w = 2 * cm1; Chris@9: double ar[3], ai[3]; Chris@9: Chris@9: for (i = 0; i < n; i += blockSize) { Chris@9: Chris@9: ar[2] = cm2; Chris@9: ar[1] = cm1; Chris@9: Chris@9: ai[2] = sm2; Chris@9: ai[1] = sm1; Chris@9: Chris@9: for (j = i, m = 0; m < blockEnd; j++, m++) { Chris@9: Chris@9: ar[0] = w * ar[1] - ar[2]; Chris@9: ar[2] = ar[1]; Chris@9: ar[1] = ar[0]; Chris@9: Chris@9: ai[0] = w * ai[1] - ai[2]; Chris@9: ai[2] = ai[1]; Chris@9: ai[1] = ai[0]; Chris@9: Chris@9: k = j + blockEnd; Chris@9: tr = ar[0] * ro[k] - ai[0] * io[k]; Chris@9: ti = ar[0] * io[k] + ai[0] * ro[k]; Chris@9: Chris@9: ro[k] = ro[j] - tr; Chris@9: io[k] = io[j] - ti; Chris@9: Chris@9: ro[j] += tr; Chris@9: io[j] += ti; Chris@9: } Chris@9: } Chris@9: Chris@9: blockEnd = blockSize; Chris@9: } Chris@9: Chris@9: if (!inverse) { Chris@9: Chris@9: double denom = (double)n; Chris@9: Chris@9: for (i = 0; i < n; i++) { Chris@9: ro[i] /= denom; Chris@9: io[i] /= denom; Chris@9: } Chris@9: } Chris@9: } Chris@9: