static int ifft(fixed fr[], fixed fi[], int m) { int mr, nn, i, j, l, k, istep, n, scale, shift; fixed qr, qi, tr, ti, wr, wi; n = 1 << m; if (n > N_WAVE) return -1; mr = 0; nn = n - 1; scale = 0; /* decimation in time - re-order data */ for (m = 1; m <= nn; ++m) { l = n; do { l >>= 1; } while (mr + l > nn); mr = (mr & (l - 1)) + l; if (mr <= m) continue; tr = fr[m]; fr[m] = fr[mr]; fr[mr] = tr; ti = fi[m]; fi[m] = fi[mr]; fi[mr] = ti; } l = 1; k = LOG2_N_WAVE - 1; while (l < n) { /* variable scaling, depending upon data */ shift = 0; for (i = 0; i < n; ++i) { j = fr[i]; if (j < 0) j = -j; m = fi[i]; if (m < 0) m = -m; if (j > 16383 || m > 16383) { shift = 1; break; } } if (shift) ++scale; /* it may not be obvious, but the shift will be performed on each data point exactly once, during this pass. */ istep = l << 1; for (m = 0; m < l; ++m) { j = m << k; /* 0 <= j < N_WAVE/2 */ wr = Sinewave[j + N_WAVE / 4]; wi = -Sinewave[j]; wi = -wi; if (shift) { wr >>= 1; wi >>= 1; } for (i = m; i < n; i += istep) { j = i + l; tr = fix_mpy(wr, fr[j]) - fix_mpy(wi, fi[j]); ti = fix_mpy(wr, fi[j]) + fix_mpy(wi, fr[j]); qr = fr[i]; qi = fi[i]; if (shift) { qr >>= 1; qi >>= 1; } fr[j] = qr - tr; fi[j] = qi - ti; fr[i] = qr + tr; fi[i] = qi + ti; } } --k; l = istep; } return scale; }
__IRAM_CODE static int fft(fixed fr[], fixed fi[], int m) { int mr, nn, i, j, l, k, istep, n; fixed qr, qi, wr, wi; n = 1 << m; if (n > N_WAVE) return -1; mr = 0; nn = n - 1; /* decimation in time - re-order data */ for (m = 1; m <= nn; ++m) { fixed tmp; l = n; do { l >>= 1; } while (mr + l > nn); mr = (mr & (l - 1)) + l; if (mr <= m) continue; tmp = fr[m]; fr[m] = fr[mr]; fr[mr] = tmp; tmp = fi[m]; fi[m] = fi[mr]; fi[mr] = tmp; } l = 1; k = LOG2_N_WAVE - 1; while (l < n) { /* fixed scaling, for proper normalization - there will be log2(n) passes, so this results in an overall factor of 1/n, distributed to maximize arithmetic accuracy. */ istep = l << 1; for (m = 0; m < l; ++m) { j = m << k; /* 0 <= j < N_WAVE/2 */ wr = Sinewave[j + N_WAVE / 4]; wi = -Sinewave[j]; wr >>= 1; wi >>= 1; for (i = m; i < n; i += istep) { fixed tr,ti; j = i + l; tr = fix_mpy(wr, fr[j]) - fix_mpy(wi, fi[j]); ti = fix_mpy(wr, fi[j]) + fix_mpy(wi, fr[j]); qr = fr[i]; qi = fi[i]; qr >>= 1; qi >>= 1; fr[j] = qr - tr; fi[j] = qi - ti; fr[i] = qr + tr; fi[i] = qi + ti; } } --k; l = istep; } return 0; }
/* fix_fft() - perform fast Fourier transform. if n>0 FFT is done, if n<0 inverse FFT is done f[n] is a complex array, INPUT AND RESULT. size of data = 2**m set inverse to 0=dft, 1=idft */ int fix_fft(fixed f[], int m, int inverse) { int mr,nn,i,j,l,k,istep, n, scale, shift; fixed qr,qi,tr,ti,wr,wi,t; n = 1<<m; if(n > N_WAVE) return -1; mr = 0; nn = n - 1; scale = 0; /* decimation in time - re-order data */ for(m=1; m<=nn; ++m) { l = n; do { l >>= 1; } while(mr+l > nn); mr = (mr & (l-1)) + l; if(mr <= m) continue; tr = f[m<<1]; f[m<<1] = f[mr<<1]; f[mr<<1] = tr; ti = f[1+(m<<1)]; f[1+(m<<1)] = f[1+(mr<<1)]; f[1+(mr<<1)] = ti; } l = 1; k = LOG2_N_WAVE-1; while(l < n) { if(inverse) { /* variable scaling, depending upon data */ shift = 0; for(i=0; i<n; ++i) { j = f[i<<1]; if(j < 0) j = -j; m = f[1+(i<<1)]; if(m < 0) m = -m; if(j > 16383 || m > 16383) { shift = 1; break; } } if(shift) ++scale; } else { /* fixed scaling, for proper normalization - there will be log2(n) passes, so this results in an overall factor of 1/n, distributed to maximize arithmetic accuracy. */ shift = 1; } /* it may not be obvious, but the shift will be performed on each data point exactly once, during this pass. */ istep = l << 1; for(m=0; m<l; ++m) { j = m << k; /* 0 <= j < N_WAVE/2 */ wr = Sinewave[j+N_WAVE/4]; wi = -Sinewave[j]; if(inverse) wi = -wi; if(shift) { wr >>= 1; wi >>= 1; } for(i=m; i<n; i+=istep) { j = i + l; tr = fix_mpy(wr,f[j<<1]) - fix_mpy(wi,f[1+(j<<1)]); ti = fix_mpy(wr,f[1+(j<<1)]) + fix_mpy(wi,f[j<<1]); qr = f[i<<1]; qi = f[1+(i<<1)]; if(shift) { qr >>= 1; qi >>= 1; } f[j<<1] = qr - tr; f[1+(j<<1)] = qi - ti; f[i<<1] = qr + tr; f[1+(i<<1)] = qi + ti; } } --k; l = istep; } return scale; }