1*28e138c6SAndroid Build Coastguard Worker /* Copyright (C) 2005-2006 Jean-Marc Valin
2*28e138c6SAndroid Build Coastguard Worker File: fftwrap.c
3*28e138c6SAndroid Build Coastguard Worker
4*28e138c6SAndroid Build Coastguard Worker Wrapper for various FFTs
5*28e138c6SAndroid Build Coastguard Worker
6*28e138c6SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without
7*28e138c6SAndroid Build Coastguard Worker modification, are permitted provided that the following conditions
8*28e138c6SAndroid Build Coastguard Worker are met:
9*28e138c6SAndroid Build Coastguard Worker
10*28e138c6SAndroid Build Coastguard Worker - Redistributions of source code must retain the above copyright
11*28e138c6SAndroid Build Coastguard Worker notice, this list of conditions and the following disclaimer.
12*28e138c6SAndroid Build Coastguard Worker
13*28e138c6SAndroid Build Coastguard Worker - Redistributions in binary form must reproduce the above copyright
14*28e138c6SAndroid Build Coastguard Worker notice, this list of conditions and the following disclaimer in the
15*28e138c6SAndroid Build Coastguard Worker documentation and/or other materials provided with the distribution.
16*28e138c6SAndroid Build Coastguard Worker
17*28e138c6SAndroid Build Coastguard Worker - Neither the name of the Xiph.org Foundation nor the names of its
18*28e138c6SAndroid Build Coastguard Worker contributors may be used to endorse or promote products derived from
19*28e138c6SAndroid Build Coastguard Worker this software without specific prior written permission.
20*28e138c6SAndroid Build Coastguard Worker
21*28e138c6SAndroid Build Coastguard Worker THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*28e138c6SAndroid Build Coastguard Worker ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*28e138c6SAndroid Build Coastguard Worker LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24*28e138c6SAndroid Build Coastguard Worker A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
25*28e138c6SAndroid Build Coastguard Worker CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26*28e138c6SAndroid Build Coastguard Worker EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27*28e138c6SAndroid Build Coastguard Worker PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28*28e138c6SAndroid Build Coastguard Worker PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29*28e138c6SAndroid Build Coastguard Worker LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30*28e138c6SAndroid Build Coastguard Worker NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31*28e138c6SAndroid Build Coastguard Worker SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*28e138c6SAndroid Build Coastguard Worker
33*28e138c6SAndroid Build Coastguard Worker */
34*28e138c6SAndroid Build Coastguard Worker
35*28e138c6SAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
36*28e138c6SAndroid Build Coastguard Worker #include "config.h"
37*28e138c6SAndroid Build Coastguard Worker #endif
38*28e138c6SAndroid Build Coastguard Worker
39*28e138c6SAndroid Build Coastguard Worker #include "arch.h"
40*28e138c6SAndroid Build Coastguard Worker #include "os_support.h"
41*28e138c6SAndroid Build Coastguard Worker
42*28e138c6SAndroid Build Coastguard Worker #define MAX_FFT_SIZE 2048
43*28e138c6SAndroid Build Coastguard Worker
44*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
maximize_range(spx_word16_t * in,spx_word16_t * out,spx_word16_t bound,int len)45*28e138c6SAndroid Build Coastguard Worker static int maximize_range(spx_word16_t *in, spx_word16_t *out, spx_word16_t bound, int len)
46*28e138c6SAndroid Build Coastguard Worker {
47*28e138c6SAndroid Build Coastguard Worker int i, shift;
48*28e138c6SAndroid Build Coastguard Worker spx_word16_t max_val = 0;
49*28e138c6SAndroid Build Coastguard Worker for (i=0;i<len;i++)
50*28e138c6SAndroid Build Coastguard Worker {
51*28e138c6SAndroid Build Coastguard Worker if (in[i]>max_val)
52*28e138c6SAndroid Build Coastguard Worker max_val = in[i];
53*28e138c6SAndroid Build Coastguard Worker if (-in[i]>max_val)
54*28e138c6SAndroid Build Coastguard Worker max_val = -in[i];
55*28e138c6SAndroid Build Coastguard Worker }
56*28e138c6SAndroid Build Coastguard Worker shift=0;
57*28e138c6SAndroid Build Coastguard Worker while (max_val <= (bound>>1) && max_val != 0)
58*28e138c6SAndroid Build Coastguard Worker {
59*28e138c6SAndroid Build Coastguard Worker max_val <<= 1;
60*28e138c6SAndroid Build Coastguard Worker shift++;
61*28e138c6SAndroid Build Coastguard Worker }
62*28e138c6SAndroid Build Coastguard Worker for (i=0;i<len;i++)
63*28e138c6SAndroid Build Coastguard Worker {
64*28e138c6SAndroid Build Coastguard Worker out[i] = SHL16(in[i], shift);
65*28e138c6SAndroid Build Coastguard Worker }
66*28e138c6SAndroid Build Coastguard Worker return shift;
67*28e138c6SAndroid Build Coastguard Worker }
68*28e138c6SAndroid Build Coastguard Worker
renorm_range(spx_word16_t * in,spx_word16_t * out,int shift,int len)69*28e138c6SAndroid Build Coastguard Worker static void renorm_range(spx_word16_t *in, spx_word16_t *out, int shift, int len)
70*28e138c6SAndroid Build Coastguard Worker {
71*28e138c6SAndroid Build Coastguard Worker int i;
72*28e138c6SAndroid Build Coastguard Worker for (i=0;i<len;i++)
73*28e138c6SAndroid Build Coastguard Worker {
74*28e138c6SAndroid Build Coastguard Worker out[i] = PSHR16(in[i], shift);
75*28e138c6SAndroid Build Coastguard Worker }
76*28e138c6SAndroid Build Coastguard Worker }
77*28e138c6SAndroid Build Coastguard Worker #endif
78*28e138c6SAndroid Build Coastguard Worker
79*28e138c6SAndroid Build Coastguard Worker #ifdef USE_SMALLFT
80*28e138c6SAndroid Build Coastguard Worker
81*28e138c6SAndroid Build Coastguard Worker #include "smallft.h"
82*28e138c6SAndroid Build Coastguard Worker #include <math.h>
83*28e138c6SAndroid Build Coastguard Worker
spx_fft_init(int size)84*28e138c6SAndroid Build Coastguard Worker void *spx_fft_init(int size)
85*28e138c6SAndroid Build Coastguard Worker {
86*28e138c6SAndroid Build Coastguard Worker struct drft_lookup *table;
87*28e138c6SAndroid Build Coastguard Worker table = speex_alloc(sizeof(struct drft_lookup));
88*28e138c6SAndroid Build Coastguard Worker spx_drft_init((struct drft_lookup *)table, size);
89*28e138c6SAndroid Build Coastguard Worker return (void*)table;
90*28e138c6SAndroid Build Coastguard Worker }
91*28e138c6SAndroid Build Coastguard Worker
spx_fft_destroy(void * table)92*28e138c6SAndroid Build Coastguard Worker void spx_fft_destroy(void *table)
93*28e138c6SAndroid Build Coastguard Worker {
94*28e138c6SAndroid Build Coastguard Worker spx_drft_clear(table);
95*28e138c6SAndroid Build Coastguard Worker speex_free(table);
96*28e138c6SAndroid Build Coastguard Worker }
97*28e138c6SAndroid Build Coastguard Worker
spx_fft(void * table,float * in,float * out)98*28e138c6SAndroid Build Coastguard Worker void spx_fft(void *table, float *in, float *out)
99*28e138c6SAndroid Build Coastguard Worker {
100*28e138c6SAndroid Build Coastguard Worker if (in==out)
101*28e138c6SAndroid Build Coastguard Worker {
102*28e138c6SAndroid Build Coastguard Worker int i;
103*28e138c6SAndroid Build Coastguard Worker float scale = 1./((struct drft_lookup *)table)->n;
104*28e138c6SAndroid Build Coastguard Worker speex_warning("FFT should not be done in-place");
105*28e138c6SAndroid Build Coastguard Worker for (i=0;i<((struct drft_lookup *)table)->n;i++)
106*28e138c6SAndroid Build Coastguard Worker out[i] = scale*in[i];
107*28e138c6SAndroid Build Coastguard Worker } else {
108*28e138c6SAndroid Build Coastguard Worker int i;
109*28e138c6SAndroid Build Coastguard Worker float scale = 1./((struct drft_lookup *)table)->n;
110*28e138c6SAndroid Build Coastguard Worker for (i=0;i<((struct drft_lookup *)table)->n;i++)
111*28e138c6SAndroid Build Coastguard Worker out[i] = scale*in[i];
112*28e138c6SAndroid Build Coastguard Worker }
113*28e138c6SAndroid Build Coastguard Worker spx_drft_forward((struct drft_lookup *)table, out);
114*28e138c6SAndroid Build Coastguard Worker }
115*28e138c6SAndroid Build Coastguard Worker
spx_ifft(void * table,float * in,float * out)116*28e138c6SAndroid Build Coastguard Worker void spx_ifft(void *table, float *in, float *out)
117*28e138c6SAndroid Build Coastguard Worker {
118*28e138c6SAndroid Build Coastguard Worker if (in==out)
119*28e138c6SAndroid Build Coastguard Worker {
120*28e138c6SAndroid Build Coastguard Worker speex_warning("FFT should not be done in-place");
121*28e138c6SAndroid Build Coastguard Worker } else {
122*28e138c6SAndroid Build Coastguard Worker int i;
123*28e138c6SAndroid Build Coastguard Worker for (i=0;i<((struct drft_lookup *)table)->n;i++)
124*28e138c6SAndroid Build Coastguard Worker out[i] = in[i];
125*28e138c6SAndroid Build Coastguard Worker }
126*28e138c6SAndroid Build Coastguard Worker spx_drft_backward((struct drft_lookup *)table, out);
127*28e138c6SAndroid Build Coastguard Worker }
128*28e138c6SAndroid Build Coastguard Worker
129*28e138c6SAndroid Build Coastguard Worker #elif defined(USE_INTEL_MKL)
130*28e138c6SAndroid Build Coastguard Worker #include <mkl.h>
131*28e138c6SAndroid Build Coastguard Worker
132*28e138c6SAndroid Build Coastguard Worker struct mkl_config {
133*28e138c6SAndroid Build Coastguard Worker DFTI_DESCRIPTOR_HANDLE desc;
134*28e138c6SAndroid Build Coastguard Worker int N;
135*28e138c6SAndroid Build Coastguard Worker };
136*28e138c6SAndroid Build Coastguard Worker
spx_fft_init(int size)137*28e138c6SAndroid Build Coastguard Worker void *spx_fft_init(int size)
138*28e138c6SAndroid Build Coastguard Worker {
139*28e138c6SAndroid Build Coastguard Worker struct mkl_config *table = (struct mkl_config *) speex_alloc(sizeof(struct mkl_config));
140*28e138c6SAndroid Build Coastguard Worker table->N = size;
141*28e138c6SAndroid Build Coastguard Worker DftiCreateDescriptor(&table->desc, DFTI_SINGLE, DFTI_REAL, 1, size);
142*28e138c6SAndroid Build Coastguard Worker DftiSetValue(table->desc, DFTI_PACKED_FORMAT, DFTI_PACK_FORMAT);
143*28e138c6SAndroid Build Coastguard Worker DftiSetValue(table->desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
144*28e138c6SAndroid Build Coastguard Worker DftiSetValue(table->desc, DFTI_FORWARD_SCALE, 1.0f / size);
145*28e138c6SAndroid Build Coastguard Worker DftiCommitDescriptor(table->desc);
146*28e138c6SAndroid Build Coastguard Worker return table;
147*28e138c6SAndroid Build Coastguard Worker }
148*28e138c6SAndroid Build Coastguard Worker
spx_fft_destroy(void * table)149*28e138c6SAndroid Build Coastguard Worker void spx_fft_destroy(void *table)
150*28e138c6SAndroid Build Coastguard Worker {
151*28e138c6SAndroid Build Coastguard Worker struct mkl_config *t = (struct mkl_config *) table;
152*28e138c6SAndroid Build Coastguard Worker DftiFreeDescriptor(t->desc);
153*28e138c6SAndroid Build Coastguard Worker speex_free(table);
154*28e138c6SAndroid Build Coastguard Worker }
155*28e138c6SAndroid Build Coastguard Worker
spx_fft(void * table,spx_word16_t * in,spx_word16_t * out)156*28e138c6SAndroid Build Coastguard Worker void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
157*28e138c6SAndroid Build Coastguard Worker {
158*28e138c6SAndroid Build Coastguard Worker struct mkl_config *t = (struct mkl_config *) table;
159*28e138c6SAndroid Build Coastguard Worker DftiComputeForward(t->desc, in, out);
160*28e138c6SAndroid Build Coastguard Worker }
161*28e138c6SAndroid Build Coastguard Worker
spx_ifft(void * table,spx_word16_t * in,spx_word16_t * out)162*28e138c6SAndroid Build Coastguard Worker void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
163*28e138c6SAndroid Build Coastguard Worker {
164*28e138c6SAndroid Build Coastguard Worker struct mkl_config *t = (struct mkl_config *) table;
165*28e138c6SAndroid Build Coastguard Worker DftiComputeBackward(t->desc, in, out);
166*28e138c6SAndroid Build Coastguard Worker }
167*28e138c6SAndroid Build Coastguard Worker
168*28e138c6SAndroid Build Coastguard Worker #elif defined(USE_INTEL_IPP)
169*28e138c6SAndroid Build Coastguard Worker
170*28e138c6SAndroid Build Coastguard Worker #include <ipps.h>
171*28e138c6SAndroid Build Coastguard Worker
172*28e138c6SAndroid Build Coastguard Worker struct ipp_fft_config
173*28e138c6SAndroid Build Coastguard Worker {
174*28e138c6SAndroid Build Coastguard Worker IppsDFTSpec_R_32f *dftSpec;
175*28e138c6SAndroid Build Coastguard Worker Ipp8u *buffer;
176*28e138c6SAndroid Build Coastguard Worker };
177*28e138c6SAndroid Build Coastguard Worker
spx_fft_init(int size)178*28e138c6SAndroid Build Coastguard Worker void *spx_fft_init(int size)
179*28e138c6SAndroid Build Coastguard Worker {
180*28e138c6SAndroid Build Coastguard Worker int bufferSize = 0;
181*28e138c6SAndroid Build Coastguard Worker int hint;
182*28e138c6SAndroid Build Coastguard Worker struct ipp_fft_config *table;
183*28e138c6SAndroid Build Coastguard Worker
184*28e138c6SAndroid Build Coastguard Worker table = (struct ipp_fft_config *)speex_alloc(sizeof(struct ipp_fft_config));
185*28e138c6SAndroid Build Coastguard Worker
186*28e138c6SAndroid Build Coastguard Worker /* there appears to be no performance difference between ippAlgHintFast and
187*28e138c6SAndroid Build Coastguard Worker ippAlgHintAccurate when using the with the floating point version
188*28e138c6SAndroid Build Coastguard Worker of the fft. */
189*28e138c6SAndroid Build Coastguard Worker hint = ippAlgHintAccurate;
190*28e138c6SAndroid Build Coastguard Worker
191*28e138c6SAndroid Build Coastguard Worker ippsDFTInitAlloc_R_32f(&table->dftSpec, size, IPP_FFT_DIV_FWD_BY_N, hint);
192*28e138c6SAndroid Build Coastguard Worker
193*28e138c6SAndroid Build Coastguard Worker ippsDFTGetBufSize_R_32f(table->dftSpec, &bufferSize);
194*28e138c6SAndroid Build Coastguard Worker table->buffer = ippsMalloc_8u(bufferSize);
195*28e138c6SAndroid Build Coastguard Worker
196*28e138c6SAndroid Build Coastguard Worker return table;
197*28e138c6SAndroid Build Coastguard Worker }
198*28e138c6SAndroid Build Coastguard Worker
spx_fft_destroy(void * table)199*28e138c6SAndroid Build Coastguard Worker void spx_fft_destroy(void *table)
200*28e138c6SAndroid Build Coastguard Worker {
201*28e138c6SAndroid Build Coastguard Worker struct ipp_fft_config *t = (struct ipp_fft_config *)table;
202*28e138c6SAndroid Build Coastguard Worker ippsFree(t->buffer);
203*28e138c6SAndroid Build Coastguard Worker ippsDFTFree_R_32f(t->dftSpec);
204*28e138c6SAndroid Build Coastguard Worker speex_free(t);
205*28e138c6SAndroid Build Coastguard Worker }
206*28e138c6SAndroid Build Coastguard Worker
spx_fft(void * table,spx_word16_t * in,spx_word16_t * out)207*28e138c6SAndroid Build Coastguard Worker void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
208*28e138c6SAndroid Build Coastguard Worker {
209*28e138c6SAndroid Build Coastguard Worker struct ipp_fft_config *t = (struct ipp_fft_config *)table;
210*28e138c6SAndroid Build Coastguard Worker ippsDFTFwd_RToPack_32f(in, out, t->dftSpec, t->buffer);
211*28e138c6SAndroid Build Coastguard Worker }
212*28e138c6SAndroid Build Coastguard Worker
spx_ifft(void * table,spx_word16_t * in,spx_word16_t * out)213*28e138c6SAndroid Build Coastguard Worker void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
214*28e138c6SAndroid Build Coastguard Worker {
215*28e138c6SAndroid Build Coastguard Worker struct ipp_fft_config *t = (struct ipp_fft_config *)table;
216*28e138c6SAndroid Build Coastguard Worker ippsDFTInv_PackToR_32f(in, out, t->dftSpec, t->buffer);
217*28e138c6SAndroid Build Coastguard Worker }
218*28e138c6SAndroid Build Coastguard Worker
219*28e138c6SAndroid Build Coastguard Worker #elif defined(USE_GPL_FFTW3)
220*28e138c6SAndroid Build Coastguard Worker
221*28e138c6SAndroid Build Coastguard Worker #include <fftw3.h>
222*28e138c6SAndroid Build Coastguard Worker
223*28e138c6SAndroid Build Coastguard Worker struct fftw_config {
224*28e138c6SAndroid Build Coastguard Worker float *in;
225*28e138c6SAndroid Build Coastguard Worker float *out;
226*28e138c6SAndroid Build Coastguard Worker fftwf_plan fft;
227*28e138c6SAndroid Build Coastguard Worker fftwf_plan ifft;
228*28e138c6SAndroid Build Coastguard Worker int N;
229*28e138c6SAndroid Build Coastguard Worker };
230*28e138c6SAndroid Build Coastguard Worker
spx_fft_init(int size)231*28e138c6SAndroid Build Coastguard Worker void *spx_fft_init(int size)
232*28e138c6SAndroid Build Coastguard Worker {
233*28e138c6SAndroid Build Coastguard Worker struct fftw_config *table = (struct fftw_config *) speex_alloc(sizeof(struct fftw_config));
234*28e138c6SAndroid Build Coastguard Worker table->in = fftwf_malloc(sizeof(float) * (size+2));
235*28e138c6SAndroid Build Coastguard Worker table->out = fftwf_malloc(sizeof(float) * (size+2));
236*28e138c6SAndroid Build Coastguard Worker
237*28e138c6SAndroid Build Coastguard Worker table->fft = fftwf_plan_dft_r2c_1d(size, table->in, (fftwf_complex *) table->out, FFTW_PATIENT);
238*28e138c6SAndroid Build Coastguard Worker table->ifft = fftwf_plan_dft_c2r_1d(size, (fftwf_complex *) table->in, table->out, FFTW_PATIENT);
239*28e138c6SAndroid Build Coastguard Worker
240*28e138c6SAndroid Build Coastguard Worker table->N = size;
241*28e138c6SAndroid Build Coastguard Worker return table;
242*28e138c6SAndroid Build Coastguard Worker }
243*28e138c6SAndroid Build Coastguard Worker
spx_fft_destroy(void * table)244*28e138c6SAndroid Build Coastguard Worker void spx_fft_destroy(void *table)
245*28e138c6SAndroid Build Coastguard Worker {
246*28e138c6SAndroid Build Coastguard Worker struct fftw_config *t = (struct fftw_config *) table;
247*28e138c6SAndroid Build Coastguard Worker fftwf_destroy_plan(t->fft);
248*28e138c6SAndroid Build Coastguard Worker fftwf_destroy_plan(t->ifft);
249*28e138c6SAndroid Build Coastguard Worker fftwf_free(t->in);
250*28e138c6SAndroid Build Coastguard Worker fftwf_free(t->out);
251*28e138c6SAndroid Build Coastguard Worker speex_free(table);
252*28e138c6SAndroid Build Coastguard Worker }
253*28e138c6SAndroid Build Coastguard Worker
254*28e138c6SAndroid Build Coastguard Worker
spx_fft(void * table,spx_word16_t * in,spx_word16_t * out)255*28e138c6SAndroid Build Coastguard Worker void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
256*28e138c6SAndroid Build Coastguard Worker {
257*28e138c6SAndroid Build Coastguard Worker int i;
258*28e138c6SAndroid Build Coastguard Worker struct fftw_config *t = (struct fftw_config *) table;
259*28e138c6SAndroid Build Coastguard Worker const int N = t->N;
260*28e138c6SAndroid Build Coastguard Worker float *iptr = t->in;
261*28e138c6SAndroid Build Coastguard Worker float *optr = t->out;
262*28e138c6SAndroid Build Coastguard Worker const float m = 1.0 / N;
263*28e138c6SAndroid Build Coastguard Worker for(i=0;i<N;++i)
264*28e138c6SAndroid Build Coastguard Worker iptr[i]=in[i] * m;
265*28e138c6SAndroid Build Coastguard Worker
266*28e138c6SAndroid Build Coastguard Worker fftwf_execute(t->fft);
267*28e138c6SAndroid Build Coastguard Worker
268*28e138c6SAndroid Build Coastguard Worker out[0] = optr[0];
269*28e138c6SAndroid Build Coastguard Worker for(i=1;i<N;++i)
270*28e138c6SAndroid Build Coastguard Worker out[i] = optr[i+1];
271*28e138c6SAndroid Build Coastguard Worker }
272*28e138c6SAndroid Build Coastguard Worker
spx_ifft(void * table,spx_word16_t * in,spx_word16_t * out)273*28e138c6SAndroid Build Coastguard Worker void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
274*28e138c6SAndroid Build Coastguard Worker {
275*28e138c6SAndroid Build Coastguard Worker int i;
276*28e138c6SAndroid Build Coastguard Worker struct fftw_config *t = (struct fftw_config *) table;
277*28e138c6SAndroid Build Coastguard Worker const int N = t->N;
278*28e138c6SAndroid Build Coastguard Worker float *iptr = t->in;
279*28e138c6SAndroid Build Coastguard Worker float *optr = t->out;
280*28e138c6SAndroid Build Coastguard Worker
281*28e138c6SAndroid Build Coastguard Worker iptr[0] = in[0];
282*28e138c6SAndroid Build Coastguard Worker iptr[1] = 0.0f;
283*28e138c6SAndroid Build Coastguard Worker for(i=1;i<N;++i)
284*28e138c6SAndroid Build Coastguard Worker iptr[i+1] = in[i];
285*28e138c6SAndroid Build Coastguard Worker iptr[N+1] = 0.0f;
286*28e138c6SAndroid Build Coastguard Worker
287*28e138c6SAndroid Build Coastguard Worker fftwf_execute(t->ifft);
288*28e138c6SAndroid Build Coastguard Worker
289*28e138c6SAndroid Build Coastguard Worker for(i=0;i<N;++i)
290*28e138c6SAndroid Build Coastguard Worker out[i] = optr[i];
291*28e138c6SAndroid Build Coastguard Worker }
292*28e138c6SAndroid Build Coastguard Worker
293*28e138c6SAndroid Build Coastguard Worker #elif defined(USE_KISS_FFT)
294*28e138c6SAndroid Build Coastguard Worker
295*28e138c6SAndroid Build Coastguard Worker #include "kiss_fftr.h"
296*28e138c6SAndroid Build Coastguard Worker #include "kiss_fft.h"
297*28e138c6SAndroid Build Coastguard Worker
298*28e138c6SAndroid Build Coastguard Worker struct kiss_config {
299*28e138c6SAndroid Build Coastguard Worker kiss_fftr_cfg forward;
300*28e138c6SAndroid Build Coastguard Worker kiss_fftr_cfg backward;
301*28e138c6SAndroid Build Coastguard Worker int N;
302*28e138c6SAndroid Build Coastguard Worker };
303*28e138c6SAndroid Build Coastguard Worker
spx_fft_init(int size)304*28e138c6SAndroid Build Coastguard Worker void *spx_fft_init(int size)
305*28e138c6SAndroid Build Coastguard Worker {
306*28e138c6SAndroid Build Coastguard Worker struct kiss_config *table;
307*28e138c6SAndroid Build Coastguard Worker table = (struct kiss_config*)speex_alloc(sizeof(struct kiss_config));
308*28e138c6SAndroid Build Coastguard Worker table->forward = kiss_fftr_alloc(size,0,NULL,NULL);
309*28e138c6SAndroid Build Coastguard Worker table->backward = kiss_fftr_alloc(size,1,NULL,NULL);
310*28e138c6SAndroid Build Coastguard Worker table->N = size;
311*28e138c6SAndroid Build Coastguard Worker return table;
312*28e138c6SAndroid Build Coastguard Worker }
313*28e138c6SAndroid Build Coastguard Worker
spx_fft_destroy(void * table)314*28e138c6SAndroid Build Coastguard Worker void spx_fft_destroy(void *table)
315*28e138c6SAndroid Build Coastguard Worker {
316*28e138c6SAndroid Build Coastguard Worker struct kiss_config *t = (struct kiss_config *)table;
317*28e138c6SAndroid Build Coastguard Worker kiss_fftr_free(t->forward);
318*28e138c6SAndroid Build Coastguard Worker kiss_fftr_free(t->backward);
319*28e138c6SAndroid Build Coastguard Worker speex_free(table);
320*28e138c6SAndroid Build Coastguard Worker }
321*28e138c6SAndroid Build Coastguard Worker
322*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
323*28e138c6SAndroid Build Coastguard Worker
spx_fft(void * table,spx_word16_t * in,spx_word16_t * out)324*28e138c6SAndroid Build Coastguard Worker void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
325*28e138c6SAndroid Build Coastguard Worker {
326*28e138c6SAndroid Build Coastguard Worker int shift;
327*28e138c6SAndroid Build Coastguard Worker struct kiss_config *t = (struct kiss_config *)table;
328*28e138c6SAndroid Build Coastguard Worker shift = maximize_range(in, in, 32000, t->N);
329*28e138c6SAndroid Build Coastguard Worker kiss_fftr2(t->forward, in, out);
330*28e138c6SAndroid Build Coastguard Worker renorm_range(in, in, shift, t->N);
331*28e138c6SAndroid Build Coastguard Worker renorm_range(out, out, shift, t->N);
332*28e138c6SAndroid Build Coastguard Worker }
333*28e138c6SAndroid Build Coastguard Worker
334*28e138c6SAndroid Build Coastguard Worker #else
335*28e138c6SAndroid Build Coastguard Worker
spx_fft(void * table,spx_word16_t * in,spx_word16_t * out)336*28e138c6SAndroid Build Coastguard Worker void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
337*28e138c6SAndroid Build Coastguard Worker {
338*28e138c6SAndroid Build Coastguard Worker int i;
339*28e138c6SAndroid Build Coastguard Worker float scale;
340*28e138c6SAndroid Build Coastguard Worker struct kiss_config *t = (struct kiss_config *)table;
341*28e138c6SAndroid Build Coastguard Worker scale = 1./t->N;
342*28e138c6SAndroid Build Coastguard Worker kiss_fftr2(t->forward, in, out);
343*28e138c6SAndroid Build Coastguard Worker for (i=0;i<t->N;i++)
344*28e138c6SAndroid Build Coastguard Worker out[i] *= scale;
345*28e138c6SAndroid Build Coastguard Worker }
346*28e138c6SAndroid Build Coastguard Worker #endif
347*28e138c6SAndroid Build Coastguard Worker
spx_ifft(void * table,spx_word16_t * in,spx_word16_t * out)348*28e138c6SAndroid Build Coastguard Worker void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
349*28e138c6SAndroid Build Coastguard Worker {
350*28e138c6SAndroid Build Coastguard Worker struct kiss_config *t = (struct kiss_config *)table;
351*28e138c6SAndroid Build Coastguard Worker kiss_fftri2(t->backward, in, out);
352*28e138c6SAndroid Build Coastguard Worker }
353*28e138c6SAndroid Build Coastguard Worker
354*28e138c6SAndroid Build Coastguard Worker
355*28e138c6SAndroid Build Coastguard Worker #else
356*28e138c6SAndroid Build Coastguard Worker
357*28e138c6SAndroid Build Coastguard Worker #error No other FFT implemented
358*28e138c6SAndroid Build Coastguard Worker
359*28e138c6SAndroid Build Coastguard Worker #endif
360*28e138c6SAndroid Build Coastguard Worker
361*28e138c6SAndroid Build Coastguard Worker
362*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
363*28e138c6SAndroid Build Coastguard Worker /*#include "smallft.h"*/
364*28e138c6SAndroid Build Coastguard Worker
365*28e138c6SAndroid Build Coastguard Worker
spx_fft_float(void * table,float * in,float * out)366*28e138c6SAndroid Build Coastguard Worker void spx_fft_float(void *table, float *in, float *out)
367*28e138c6SAndroid Build Coastguard Worker {
368*28e138c6SAndroid Build Coastguard Worker int i;
369*28e138c6SAndroid Build Coastguard Worker #ifdef USE_SMALLFT
370*28e138c6SAndroid Build Coastguard Worker int N = ((struct drft_lookup *)table)->n;
371*28e138c6SAndroid Build Coastguard Worker #elif defined(USE_KISS_FFT)
372*28e138c6SAndroid Build Coastguard Worker int N = ((struct kiss_config *)table)->N;
373*28e138c6SAndroid Build Coastguard Worker #else
374*28e138c6SAndroid Build Coastguard Worker #endif
375*28e138c6SAndroid Build Coastguard Worker #ifdef VAR_ARRAYS
376*28e138c6SAndroid Build Coastguard Worker spx_word16_t _in[N];
377*28e138c6SAndroid Build Coastguard Worker spx_word16_t _out[N];
378*28e138c6SAndroid Build Coastguard Worker #else
379*28e138c6SAndroid Build Coastguard Worker spx_word16_t _in[MAX_FFT_SIZE];
380*28e138c6SAndroid Build Coastguard Worker spx_word16_t _out[MAX_FFT_SIZE];
381*28e138c6SAndroid Build Coastguard Worker #endif
382*28e138c6SAndroid Build Coastguard Worker for (i=0;i<N;i++)
383*28e138c6SAndroid Build Coastguard Worker _in[i] = (int)floor(.5+in[i]);
384*28e138c6SAndroid Build Coastguard Worker spx_fft(table, _in, _out);
385*28e138c6SAndroid Build Coastguard Worker for (i=0;i<N;i++)
386*28e138c6SAndroid Build Coastguard Worker out[i] = _out[i];
387*28e138c6SAndroid Build Coastguard Worker #if 0
388*28e138c6SAndroid Build Coastguard Worker if (!fixed_point)
389*28e138c6SAndroid Build Coastguard Worker {
390*28e138c6SAndroid Build Coastguard Worker float scale;
391*28e138c6SAndroid Build Coastguard Worker struct drft_lookup t;
392*28e138c6SAndroid Build Coastguard Worker spx_drft_init(&t, ((struct kiss_config *)table)->N);
393*28e138c6SAndroid Build Coastguard Worker scale = 1./((struct kiss_config *)table)->N;
394*28e138c6SAndroid Build Coastguard Worker for (i=0;i<((struct kiss_config *)table)->N;i++)
395*28e138c6SAndroid Build Coastguard Worker out[i] = scale*in[i];
396*28e138c6SAndroid Build Coastguard Worker spx_drft_forward(&t, out);
397*28e138c6SAndroid Build Coastguard Worker spx_drft_clear(&t);
398*28e138c6SAndroid Build Coastguard Worker }
399*28e138c6SAndroid Build Coastguard Worker #endif
400*28e138c6SAndroid Build Coastguard Worker }
401*28e138c6SAndroid Build Coastguard Worker
spx_ifft_float(void * table,float * in,float * out)402*28e138c6SAndroid Build Coastguard Worker void spx_ifft_float(void *table, float *in, float *out)
403*28e138c6SAndroid Build Coastguard Worker {
404*28e138c6SAndroid Build Coastguard Worker int i;
405*28e138c6SAndroid Build Coastguard Worker #ifdef USE_SMALLFT
406*28e138c6SAndroid Build Coastguard Worker int N = ((struct drft_lookup *)table)->n;
407*28e138c6SAndroid Build Coastguard Worker #elif defined(USE_KISS_FFT)
408*28e138c6SAndroid Build Coastguard Worker int N = ((struct kiss_config *)table)->N;
409*28e138c6SAndroid Build Coastguard Worker #else
410*28e138c6SAndroid Build Coastguard Worker #endif
411*28e138c6SAndroid Build Coastguard Worker #ifdef VAR_ARRAYS
412*28e138c6SAndroid Build Coastguard Worker spx_word16_t _in[N];
413*28e138c6SAndroid Build Coastguard Worker spx_word16_t _out[N];
414*28e138c6SAndroid Build Coastguard Worker #else
415*28e138c6SAndroid Build Coastguard Worker spx_word16_t _in[MAX_FFT_SIZE];
416*28e138c6SAndroid Build Coastguard Worker spx_word16_t _out[MAX_FFT_SIZE];
417*28e138c6SAndroid Build Coastguard Worker #endif
418*28e138c6SAndroid Build Coastguard Worker for (i=0;i<N;i++)
419*28e138c6SAndroid Build Coastguard Worker _in[i] = (int)floor(.5+in[i]);
420*28e138c6SAndroid Build Coastguard Worker spx_ifft(table, _in, _out);
421*28e138c6SAndroid Build Coastguard Worker for (i=0;i<N;i++)
422*28e138c6SAndroid Build Coastguard Worker out[i] = _out[i];
423*28e138c6SAndroid Build Coastguard Worker #if 0
424*28e138c6SAndroid Build Coastguard Worker if (!fixed_point)
425*28e138c6SAndroid Build Coastguard Worker {
426*28e138c6SAndroid Build Coastguard Worker int i;
427*28e138c6SAndroid Build Coastguard Worker struct drft_lookup t;
428*28e138c6SAndroid Build Coastguard Worker spx_drft_init(&t, ((struct kiss_config *)table)->N);
429*28e138c6SAndroid Build Coastguard Worker for (i=0;i<((struct kiss_config *)table)->N;i++)
430*28e138c6SAndroid Build Coastguard Worker out[i] = in[i];
431*28e138c6SAndroid Build Coastguard Worker spx_drft_backward(&t, out);
432*28e138c6SAndroid Build Coastguard Worker spx_drft_clear(&t);
433*28e138c6SAndroid Build Coastguard Worker }
434*28e138c6SAndroid Build Coastguard Worker #endif
435*28e138c6SAndroid Build Coastguard Worker }
436*28e138c6SAndroid Build Coastguard Worker
437*28e138c6SAndroid Build Coastguard Worker #else
438*28e138c6SAndroid Build Coastguard Worker
spx_fft_float(void * table,float * in,float * out)439*28e138c6SAndroid Build Coastguard Worker void spx_fft_float(void *table, float *in, float *out)
440*28e138c6SAndroid Build Coastguard Worker {
441*28e138c6SAndroid Build Coastguard Worker spx_fft(table, in, out);
442*28e138c6SAndroid Build Coastguard Worker }
spx_ifft_float(void * table,float * in,float * out)443*28e138c6SAndroid Build Coastguard Worker void spx_ifft_float(void *table, float *in, float *out)
444*28e138c6SAndroid Build Coastguard Worker {
445*28e138c6SAndroid Build Coastguard Worker spx_ifft(table, in, out);
446*28e138c6SAndroid Build Coastguard Worker }
447*28e138c6SAndroid Build Coastguard Worker
448*28e138c6SAndroid Build Coastguard Worker #endif
449