1 /* Copyright (C) 2005-2006 Jean-Marc Valin
4 Wrapper for various FFTs
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
13 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
17 - Neither the name of the Xiph.org Foundation nor the names of its
18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
25 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 #include "os_support.h"
42 #define MAX_FFT_SIZE 2048
45 static int maximize_range(spx_word16_t *in, spx_word16_t *out, spx_word16_t bound, int len)
48 spx_word16_t max_val = 0;
57 while (max_val <= (bound>>1) && max_val != 0)
64 out[i] = SHL16(in[i], shift);
69 static void renorm_range(spx_word16_t *in, spx_word16_t *out, int shift, int len)
74 out[i] = PSHR16(in[i], shift);
84 void *spx_fft_init(int size)
86 struct drft_lookup *table;
87 table = speex_alloc(sizeof(struct drft_lookup));
88 spx_drft_init((struct drft_lookup *)table, size);
92 void spx_fft_destroy(void *table)
94 spx_drft_clear(table);
98 void spx_fft(void *table, float *in, float *out)
103 float scale = 1./((struct drft_lookup *)table)->n;
104 speex_warning("FFT should not be done in-place");
105 for (i=0;i<((struct drft_lookup *)table)->n;i++)
106 out[i] = scale*in[i];
109 float scale = 1./((struct drft_lookup *)table)->n;
110 for (i=0;i<((struct drft_lookup *)table)->n;i++)
111 out[i] = scale*in[i];
113 spx_drft_forward((struct drft_lookup *)table, out);
116 void spx_ifft(void *table, float *in, float *out)
120 speex_warning("FFT should not be done in-place");
123 for (i=0;i<((struct drft_lookup *)table)->n;i++)
126 spx_drft_backward((struct drft_lookup *)table, out);
129 #elif defined(USE_INTEL_MKL)
133 DFTI_DESCRIPTOR_HANDLE desc;
137 void *spx_fft_init(int size)
139 struct mkl_config *table = (struct mkl_config *) speex_alloc(sizeof(struct mkl_config));
141 DftiCreateDescriptor(&table->desc, DFTI_SINGLE, DFTI_REAL, 1, size);
142 DftiSetValue(table->desc, DFTI_PACKED_FORMAT, DFTI_PACK_FORMAT);
143 DftiSetValue(table->desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
144 DftiSetValue(table->desc, DFTI_FORWARD_SCALE, 1.0f / size);
145 DftiCommitDescriptor(table->desc);
149 void spx_fft_destroy(void *table)
151 struct mkl_config *t = (struct mkl_config *) table;
152 DftiFreeDescriptor(t->desc);
156 void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
158 struct mkl_config *t = (struct mkl_config *) table;
159 DftiComputeForward(t->desc, in, out);
162 void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
164 struct mkl_config *t = (struct mkl_config *) table;
165 DftiComputeBackward(t->desc, in, out);
168 #elif defined(USE_GPL_FFTW3)
180 void *spx_fft_init(int size)
182 struct fftw_config *table = (struct fftw_config *) speex_alloc(sizeof(struct fftw_config));
183 table->in = fftwf_malloc(sizeof(float) * (size+2));
184 table->out = fftwf_malloc(sizeof(float) * (size+2));
186 table->fft = fftwf_plan_dft_r2c_1d(size, table->in, (fftwf_complex *) table->out, FFTW_PATIENT);
187 table->ifft = fftwf_plan_dft_c2r_1d(size, (fftwf_complex *) table->in, table->out, FFTW_PATIENT);
193 void spx_fft_destroy(void *table)
195 struct fftw_config *t = (struct fftw_config *) table;
196 fftwf_destroy_plan(t->fft);
197 fftwf_destroy_plan(t->ifft);
204 void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
207 struct fftw_config *t = (struct fftw_config *) table;
210 float *optr = t->out;
211 const float m = 1.0 / N;
215 fftwf_execute(t->fft);
222 void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
225 struct fftw_config *t = (struct fftw_config *) table;
228 float *optr = t->out;
236 fftwf_execute(t->ifft);
242 #elif defined(USE_KISS_FFT)
244 #include "kiss_fftr.h"
245 #include "kiss_fft.h"
248 kiss_fftr_cfg forward;
249 kiss_fftr_cfg backward;
253 void *spx_fft_init(int size)
255 struct kiss_config *table;
256 table = (struct kiss_config*)speex_alloc(sizeof(struct kiss_config));
257 table->forward = kiss_fftr_alloc(size,0,NULL,NULL);
258 table->backward = kiss_fftr_alloc(size,1,NULL,NULL);
263 void spx_fft_destroy(void *table)
265 struct kiss_config *t = (struct kiss_config *)table;
266 kiss_fftr_free(t->forward);
267 kiss_fftr_free(t->backward);
273 void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
276 struct kiss_config *t = (struct kiss_config *)table;
277 shift = maximize_range(in, in, 32000, t->N);
278 kiss_fftr2(t->forward, in, out);
279 renorm_range(in, in, shift, t->N);
280 renorm_range(out, out, shift, t->N);
285 void spx_fft(void *table, spx_word16_t *in, spx_word16_t *out)
289 struct kiss_config *t = (struct kiss_config *)table;
291 kiss_fftr2(t->forward, in, out);
297 void spx_ifft(void *table, spx_word16_t *in, spx_word16_t *out)
299 struct kiss_config *t = (struct kiss_config *)table;
300 kiss_fftri2(t->backward, in, out);
306 #error No other FFT implemented
312 /*#include "smallft.h"*/
315 void spx_fft_float(void *table, float *in, float *out)
319 int N = ((struct drft_lookup *)table)->n;
320 #elif defined(USE_KISS_FFT)
321 int N = ((struct kiss_config *)table)->N;
326 spx_word16_t _out[N];
328 spx_word16_t _in[MAX_FFT_SIZE];
329 spx_word16_t _out[MAX_FFT_SIZE];
332 _in[i] = (int)floor(.5+in[i]);
333 spx_fft(table, _in, _out);
340 struct drft_lookup t;
341 spx_drft_init(&t, ((struct kiss_config *)table)->N);
342 scale = 1./((struct kiss_config *)table)->N;
343 for (i=0;i<((struct kiss_config *)table)->N;i++)
344 out[i] = scale*in[i];
345 spx_drft_forward(&t, out);
351 void spx_ifft_float(void *table, float *in, float *out)
355 int N = ((struct drft_lookup *)table)->n;
356 #elif defined(USE_KISS_FFT)
357 int N = ((struct kiss_config *)table)->N;
362 spx_word16_t _out[N];
364 spx_word16_t _in[MAX_FFT_SIZE];
365 spx_word16_t _out[MAX_FFT_SIZE];
368 _in[i] = (int)floor(.5+in[i]);
369 spx_ifft(table, _in, _out);
376 struct drft_lookup t;
377 spx_drft_init(&t, ((struct kiss_config *)table)->N);
378 for (i=0;i<((struct kiss_config *)table)->N;i++)
380 spx_drft_backward(&t, out);
388 void spx_fft_float(void *table, float *in, float *out)
390 spx_fft(table, in, out);
392 void spx_ifft_float(void *table, float *in, float *out)
394 spx_ifft(table, in, out);