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