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