Chris@337: Chris@337: /* Public domain FFT implementation from Don Cross. */ Chris@337: Chris@337: static void Chris@337: fft(unsigned int n, bool inverse, Chris@337: const double *ri, const double *ii, Chris@337: double *ro, double *io) Chris@337: { Chris@337: if (!ri || !ro || !io) return; Chris@337: Chris@337: unsigned int bits; Chris@337: unsigned int i, j, k, m; Chris@337: unsigned int blockSize, blockEnd; Chris@337: Chris@337: double tr, ti; Chris@337: Chris@337: if (n < 2) return; Chris@337: if (n & (n-1)) return; Chris@337: Chris@337: double angle = 2.0 * M_PI; Chris@337: if (inverse) angle = -angle; Chris@337: Chris@337: for (i = 0; ; ++i) { Chris@337: if (n & (1 << i)) { Chris@337: bits = i; Chris@337: break; Chris@337: } Chris@337: } Chris@337: Chris@337: int table[n]; Chris@337: Chris@337: for (i = 0; i < n; ++i) { Chris@337: m = i; Chris@337: for (j = k = 0; j < bits; ++j) { Chris@337: k = (k << 1) | (m & 1); Chris@337: m >>= 1; Chris@337: } Chris@337: table[i] = k; Chris@337: } Chris@337: Chris@337: if (ii) { Chris@337: for (i = 0; i < n; ++i) { Chris@337: ro[table[i]] = ri[i]; Chris@337: io[table[i]] = ii[i]; Chris@337: } Chris@337: } else { Chris@337: for (i = 0; i < n; ++i) { Chris@337: ro[table[i]] = ri[i]; Chris@337: io[table[i]] = 0.0; Chris@337: } Chris@337: } Chris@337: Chris@337: blockEnd = 1; Chris@337: Chris@337: for (blockSize = 2; blockSize <= n; blockSize <<= 1) { Chris@337: Chris@337: double delta = angle / (double)blockSize; Chris@337: double sm2 = -sin(-2 * delta); Chris@337: double sm1 = -sin(-delta); Chris@337: double cm2 = cos(-2 * delta); Chris@337: double cm1 = cos(-delta); Chris@337: double w = 2 * cm1; Chris@337: double ar[3], ai[3]; Chris@337: Chris@337: for (i = 0; i < n; i += blockSize) { Chris@337: Chris@337: ar[2] = cm2; Chris@337: ar[1] = cm1; Chris@337: Chris@337: ai[2] = sm2; Chris@337: ai[1] = sm1; Chris@337: Chris@337: for (j = i, m = 0; m < blockEnd; j++, m++) { Chris@337: Chris@337: ar[0] = w * ar[1] - ar[2]; Chris@337: ar[2] = ar[1]; Chris@337: ar[1] = ar[0]; Chris@337: Chris@337: ai[0] = w * ai[1] - ai[2]; Chris@337: ai[2] = ai[1]; Chris@337: ai[1] = ai[0]; Chris@337: Chris@337: k = j + blockEnd; Chris@337: tr = ar[0] * ro[k] - ai[0] * io[k]; Chris@337: ti = ar[0] * io[k] + ai[0] * ro[k]; Chris@337: Chris@337: ro[k] = ro[j] - tr; Chris@337: io[k] = io[j] - ti; Chris@337: Chris@337: ro[j] += tr; Chris@337: io[j] += ti; Chris@337: } Chris@337: } Chris@337: Chris@337: blockEnd = blockSize; Chris@337: } Chris@337: Chris@337: if (inverse) { Chris@337: Chris@337: double denom = (double)n; Chris@337: Chris@337: for (i = 0; i < n; i++) { Chris@337: ro[i] /= denom; Chris@337: io[i] /= denom; Chris@337: } Chris@337: } Chris@337: } Chris@337: