michael@0: /******************************************************************** michael@0: * * michael@0: * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * michael@0: * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * michael@0: * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * michael@0: * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * michael@0: * * michael@0: * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 * michael@0: * by the Xiph.Org Foundation http://www.xiph.org/ * michael@0: * * michael@0: ******************************************************************** michael@0: michael@0: function: *unnormalized* fft transform michael@0: last mod: $Id: smallft.c 16227 2009-07-08 06:58:46Z xiphmont $ michael@0: michael@0: ********************************************************************/ michael@0: michael@0: /* FFT implementation from OggSquish, minus cosine transforms, michael@0: * minus all but radix 2/4 case. In Vorbis we only need this michael@0: * cut-down version. michael@0: * michael@0: * To do more than just power-of-two sized vectors, see the full michael@0: * version I wrote for NetLib. michael@0: * michael@0: * Note that the packing is a little strange; rather than the FFT r/i michael@0: * packing following R_0, I_n, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1, michael@0: * it follows R_0, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1, I_n like the michael@0: * FORTRAN version michael@0: */ michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include "smallft.h" michael@0: #include "os.h" michael@0: #include "misc.h" michael@0: michael@0: static void drfti1(int n, float *wa, int *ifac){ michael@0: static int ntryh[4] = { 4,2,3,5 }; michael@0: static float tpi = 6.28318530717958648f; michael@0: float arg,argh,argld,fi; michael@0: int ntry=0,i,j=-1; michael@0: int k1, l1, l2, ib; michael@0: int ld, ii, ip, is, nq, nr; michael@0: int ido, ipm, nfm1; michael@0: int nl=n; michael@0: int nf=0; michael@0: michael@0: L101: michael@0: j++; michael@0: if (j < 4) michael@0: ntry=ntryh[j]; michael@0: else michael@0: ntry+=2; michael@0: michael@0: L104: michael@0: nq=nl/ntry; michael@0: nr=nl-ntry*nq; michael@0: if (nr!=0) goto L101; michael@0: michael@0: nf++; michael@0: ifac[nf+1]=ntry; michael@0: nl=nq; michael@0: if(ntry!=2)goto L107; michael@0: if(nf==1)goto L107; michael@0: michael@0: for (i=1;i>1; michael@0: ipp2=ip; michael@0: idp2=ido; michael@0: nbd=(ido-1)>>1; michael@0: t0=l1*ido; michael@0: t10=ip*ido; michael@0: michael@0: if(ido==1)goto L119; michael@0: for(ik=0;ikl1){ michael@0: for(j=1;j>1; michael@0: ipp2=ip; michael@0: ipph=(ip+1)>>1; michael@0: if(idol1)goto L139; michael@0: michael@0: is= -ido-1; michael@0: t1=0; michael@0: for(j=1;jn==1)return; michael@0: drftf1(l->n,data,l->trigcache,l->trigcache+l->n,l->splitcache); michael@0: } michael@0: michael@0: void drft_backward(drft_lookup *l,float *data){ michael@0: if (l->n==1)return; michael@0: drftb1(l->n,data,l->trigcache,l->trigcache+l->n,l->splitcache); michael@0: } michael@0: michael@0: void drft_init(drft_lookup *l,int n){ michael@0: l->n=n; michael@0: l->trigcache=_ogg_calloc(3*n,sizeof(*l->trigcache)); michael@0: l->splitcache=_ogg_calloc(32,sizeof(*l->splitcache)); michael@0: fdrffti(n, l->trigcache, l->splitcache); michael@0: } michael@0: michael@0: void drft_clear(drft_lookup *l){ michael@0: if(l){ michael@0: if(l->trigcache)_ogg_free(l->trigcache); michael@0: if(l->splitcache)_ogg_free(l->splitcache); michael@0: memset(l,0,sizeof(*l)); michael@0: } michael@0: }