/* ** Algorithm: complex multiplication ** ** Performance: Bad accuracy, great speed. ** ** The simplest, way of generating trig values. Note, this method is ** not stable, and errors accumulate rapidly. ** ** Computation: 2 *, 1 + per value. */ #include "m_pd.h" #include "m_fixed.h" #define TRIG_FAST #ifdef TRIG_FAST char mtrig_algorithm[] = "Simple"; #define TRIG_VARS \ t_fixed t_c,t_s; #define TRIG_INIT(k,c,s) \ { \ t_c = fcostab[k]; \ t_s = fsintab[k]; \ c = itofix(1); \ s = 0; \ } #define TRIG_NEXT(k,c,s) \ { \ t_fixed t = c; \ c = mult(t,t_c) - mult(s,t_s); \ s = mult(t,t_s) + mult(s,t_c); \ } #define TRIG_23(k,c1,s1,c2,s2,c3,s3) \ { \ c2 = mult(c1,c1) - mult(s1,s1); \ s2 = (mult(c1,s1)<<2); \ c3 = mult(c2,c1) - mult(s2,s1); \ s3 = mult(c2,s1) + mult(s2,c1); \ } #endif #define TRIG_RESET(k,c,s) /* ** Algorithm: O. Buneman's trig generator. ** ** Performance: Good accuracy, mediocre speed. ** ** Manipulates a log(n) table to stably create n evenly spaced trig ** values. The newly generated values lay halfway between two ** known values, and are calculated by appropriatelly scaling the ** average of the known trig values appropriatelly according to the ** angle between them. This process is inherently stable; and is ** about as accurate as most trig library functions. The errors ** caused by this code segment are primarily due to the less stable ** method to calculate values for 2t and s 3t. Note: I believe this ** algorithm is patented(!), see readme file for more details. ** ** Computation: 1 +, 1 *, much integer math, per trig value ** */ #ifdef TRIG_GOOD #define TRIG_VARS \ int t_lam=0; \ double coswrk[TRIG_TABLE_SIZE],sinwrk[TRIG_TABLE_SIZE]; #define TRIG_INIT(k,c,s) \ { \ int i; \ for (i=0 ; i<=k ; i++) \ {coswrk[i]=fcostab[i];sinwrk[i]=fsintab[i];} \ t_lam = 0; \ c = 1; \ s = 0; \ } #define TRIG_NEXT(k,c,s) \ { \ int i,j; \ (t_lam)++; \ for (i=0 ; !((1<1) \ { \ for (j=k-i+2 ; (1<>1; (!((k2^=k)&k)); k>>=1); if (k1>k2) { aa=fz[k1];fz[k1]=fz[k2];fz[k2]=aa; } } for ( k=0 ; (1<> 1; fi = fz; gi = fi + kx; fn = fz + n; do { t_fixed g0,f0,f1,g1,f2,g2,f3,g3; f1 = fi[0 ] - fi[k1]; f0 = fi[0 ] + fi[k1]; f3 = fi[k2] - fi[k3]; f2 = fi[k2] + fi[k3]; fi[k2] = f0 - f2; fi[0 ] = f0 + f2; fi[k3] = f1 - f3; fi[k1] = f1 + f3; g1 = gi[0 ] - gi[k1]; g0 = gi[0 ] + gi[k1]; g3 = FFTmult(SQRT2, gi[k3]); g2 = FFTmult(SQRT2, gi[k2]); gi[k2] = g0 - g2; gi[0 ] = g0 + g2; gi[k3] = g1 - g3; gi[k1] = g1 + g3; gi += k4; fi += k4; } while (fi>1; real[j] = (q-t)>>1; imag[i] = (s-r)>>1; imag[j] = (s+r)>>1; } imayer_fht(real,n); imayer_fht(imag,n); } void imayer_ifft(int n, t_fixed *real, t_fixed *imag) { t_fixed a,b,c,d; t_fixed q,r,s,t; int i,j,k; imayer_fht(real,n); imayer_fht(imag,n); for (i=1,j=n-1,k=n/2;i>1; imag[j] = (s-r)>>1; real[i] = (q-t)>>1; real[j] = (q+t)>>1; } } void imayer_realfft(int n, t_fixed *real) { #ifdef ROCKBOX t_fixed a,b; #else t_fixed a,b,c,d; #endif int i,j,k; imayer_fht(real,n); for (i=1,j=n-1,k=n/2;i>1; real[i] = (a+b)>>1; } } void imayer_realifft(int n, t_fixed *real) { #ifdef ROCKBOX t_fixed a,b; #else t_fixed a,b,c,d; #endif int i,j,k; for (i=1,j=n-1,k=n/2;i int writetables() { int i; printf("/* Tables for fixed point lookup with %d bit precision*/\n\n",fix1); printf("static int fsintab[TRIG_TAB_SIZE]= {\n"); for (i=0;i %f %f\n",fixtof(r[i]),fixtof(im[i]),\ fr[i],fim[i]);\ fprintf(stderr,"\n\n"); int main() { int i; t_fixed r[256]; t_fixed im[256]; float fr[256]; float fim[256]; #if 1 writetables(); exit(0); #endif #if 0 t_fixed c1,s1,c2,s2,c3,s3; int k; int i; TRIG_VARS; for (k=2;k<10;k+=2) { TRIG_INIT(k,c1,s1); for (i=0;i<8;i++) { TRIG_NEXT(k,c1,s1); TRIG_23(k,c1,s1,c2,s2,c3,s3); printf("TRIG value k=%d,%d val1 = %f %f\n",k,i,fixtof(c1),fixtof(s1)); } } #endif #if 1 #define NP 16 for (i=0;i