1 /********************************************************************
3 * THIS FILE IS PART OF THE OggGhost SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE OggGhost SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
9 * the Xiph.Org FOundation http://www.xiph.org/ *
11 ********************************************************************
13 function: unnormalized powers-of-two forward fft transform
14 last mod: $Id: smallft.c 7573 2004-08-16 01:26:52Z conrad $
16 ********************************************************************/
18 /* FFT implementation from OggSquish, minus cosine transforms,
19 * minus all but radix 2/4 case. In Vorbis we only need this
22 * To do more than just power-of-two sized vectors, see the full
23 * version I wrote for NetLib.
25 * Note that the packing is a little strange; rather than the FFT r/i
26 * packing following R_0, R_n, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1,
27 * it follows R_0, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1, I_n like the
36 static int drfti1(int n
, double *wa
, int *ifac
){
37 static int ntryh
[2] = { 4,2 };
38 static double tpi
= 6.28318530717958648f
;
39 double arg
,argh
,argld
,fi
;
42 int ld
, ii
, ip
, is
, nq
, nr
;
51 else // powers of two only in this one, sorry
82 for (k1
=0;k1
<nfm1
;k1
++){
92 argld
=(double)ld
*argh
;
94 for (ii
=2;ii
<ido
;ii
+=2){
107 static int fdrffti(int n
, double *wsave
, int *ifac
){
108 if (n
== 1) return 0;
109 return drfti1(n
, wsave
, ifac
);
112 static void dradf2(int ido
,int l1
,double *cc
,double *ch
,double *wa1
){
115 int t0
,t1
,t2
,t3
,t4
,t5
,t6
;
121 ch
[t1
<<1]=cc
[t1
]+cc
[t2
];
122 ch
[(t1
<<1)+t3
-1]=cc
[t1
]-cc
[t2
];
142 tr2
=wa1
[i
-2]*cc
[t3
-1]+wa1
[i
-1]*cc
[t3
];
143 ti2
=wa1
[i
-2]*cc
[t3
]-wa1
[i
-1]*cc
[t3
-1];
146 ch
[t6
-1]=cc
[t5
-1]+tr2
;
147 ch
[t4
-1]=cc
[t5
-1]-tr2
;
167 static void dradf4(int ido
,int l1
,double *cc
,double *ch
,double *wa1
,
168 double *wa2
,double *wa3
){
169 static double hsqt2
= .70710678118654752f
;
170 int i
,k
,t0
,t1
,t2
,t3
,t4
,t5
,t6
;
171 double ci2
,ci3
,ci4
,cr2
,cr3
,cr4
,ti1
,ti2
,ti3
,ti4
,tr1
,tr2
,tr3
,tr4
;
183 ch
[t5
=t3
<<2]=tr1
+tr2
;
184 ch
[(ido
<<2)+t5
-1]=tr2
-tr1
;
185 ch
[(t5
+=(ido
<<1))-1]=cc
[t3
]-cc
[t4
];
186 ch
[t5
]=cc
[t2
]-cc
[t1
];
209 cr2
=wa1
[i
-2]*cc
[t3
-1]+wa1
[i
-1]*cc
[t3
];
210 ci2
=wa1
[i
-2]*cc
[t3
]-wa1
[i
-1]*cc
[t3
-1];
212 cr3
=wa2
[i
-2]*cc
[t3
-1]+wa2
[i
-1]*cc
[t3
];
213 ci3
=wa2
[i
-2]*cc
[t3
]-wa2
[i
-1]*cc
[t3
-1];
215 cr4
=wa3
[i
-2]*cc
[t3
-1]+wa3
[i
-1]*cc
[t3
];
216 ci4
=wa3
[i
-2]*cc
[t3
]-wa3
[i
-1]*cc
[t3
-1];
246 t2
=(t1
=t0
+ido
-1)+(t0
<<1);
253 ti1
=-hsqt2
*(cc
[t1
]+cc
[t2
]);
254 tr1
=hsqt2
*(cc
[t1
]-cc
[t2
]);
256 ch
[t4
-1]=tr1
+cc
[t6
-1];
257 ch
[t4
+t5
-1]=cc
[t6
-1]-tr1
;
259 ch
[t4
]=ti1
-cc
[t1
+t0
];
260 ch
[t4
+t5
]=ti1
+cc
[t1
+t0
];
269 static void drftf1(int n
,double *c
,double *ch
,double *wa
,int *ifac
){
272 int ip
,iw
,ido
,idl1
,ix2
,ix3
;
279 for(k1
=0;k1
<nf
;k1
++){
293 dradf4(ido
,l1
,ch
,c
,wa
+iw
-1,wa
+ix2
-1,wa
+ix3
-1);
295 dradf4(ido
,l1
,c
,ch
,wa
+iw
-1,wa
+ix2
-1,wa
+ix3
-1);
301 dradf2(ido
,l1
,c
,ch
,wa
+iw
-1);
305 dradf2(ido
,l1
,ch
,c
,wa
+iw
-1);
313 for(i
=0;i
<n
;i
++)c
[i
]=ch
[i
];
316 void drft_forward(drft_lookup
*l
,double *data
){
319 drftf1(l
->n
,data
,work
,l
->trigcache
,l
->splitcache
);
322 int drft_init(drft_lookup
*l
,int n
){
324 l
->trigcache
=calloc(2*n
,sizeof(*l
->trigcache
));
325 l
->splitcache
=calloc(32,sizeof(*l
->splitcache
));
326 return fdrffti(n
, l
->trigcache
, l
->splitcache
);
329 void drft_clear(drft_lookup
*l
){
331 if(l
->trigcache
)free(l
->trigcache
);
332 if(l
->splitcache
)free(l
->splitcache
);
333 memset(l
,0,sizeof(*l
));