michael@0: /*Copyright (c) 2003-2004, Mark Borgerding michael@0: Lots of modifications by Jean-Marc Valin michael@0: Copyright (c) 2005-2007, Xiph.Org Foundation michael@0: Copyright (c) 2008, Xiph.Org Foundation, CSIRO michael@0: michael@0: All rights reserved. michael@0: michael@0: Redistribution and use in source and binary forms, with or without michael@0: modification, are permitted provided that the following conditions are met: michael@0: michael@0: * Redistributions of source code must retain the above copyright notice, michael@0: this list of conditions and the following disclaimer. michael@0: * Redistributions in binary form must reproduce the above copyright notice, michael@0: this list of conditions and the following disclaimer in the michael@0: documentation and/or other materials provided with the distribution. michael@0: michael@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" michael@0: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE michael@0: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE michael@0: ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE michael@0: LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR michael@0: CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF michael@0: SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS michael@0: INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN michael@0: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) michael@0: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE michael@0: POSSIBILITY OF SUCH DAMAGE.*/ michael@0: michael@0: #ifndef KISS_FFT_H michael@0: #define KISS_FFT_H michael@0: michael@0: #include michael@0: #include michael@0: #include "arch.h" michael@0: michael@0: #ifdef __cplusplus michael@0: extern "C" { michael@0: #endif michael@0: michael@0: #ifdef USE_SIMD michael@0: # include michael@0: # define kiss_fft_scalar __m128 michael@0: #define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes) michael@0: #else michael@0: #define KISS_FFT_MALLOC opus_alloc michael@0: #endif michael@0: michael@0: #ifdef FIXED_POINT michael@0: #include "arch.h" michael@0: michael@0: # define kiss_fft_scalar opus_int32 michael@0: # define kiss_twiddle_scalar opus_int16 michael@0: michael@0: michael@0: #else michael@0: # ifndef kiss_fft_scalar michael@0: /* default is float */ michael@0: # define kiss_fft_scalar float michael@0: # define kiss_twiddle_scalar float michael@0: # define KF_SUFFIX _celt_single michael@0: # endif michael@0: #endif michael@0: michael@0: typedef struct { michael@0: kiss_fft_scalar r; michael@0: kiss_fft_scalar i; michael@0: }kiss_fft_cpx; michael@0: michael@0: typedef struct { michael@0: kiss_twiddle_scalar r; michael@0: kiss_twiddle_scalar i; michael@0: }kiss_twiddle_cpx; michael@0: michael@0: #define MAXFACTORS 8 michael@0: /* e.g. an fft of length 128 has 4 factors michael@0: as far as kissfft is concerned michael@0: 4*4*4*2 michael@0: */ michael@0: michael@0: typedef struct kiss_fft_state{ michael@0: int nfft; michael@0: #ifndef FIXED_POINT michael@0: kiss_fft_scalar scale; michael@0: #endif michael@0: int shift; michael@0: opus_int16 factors[2*MAXFACTORS]; michael@0: const opus_int16 *bitrev; michael@0: const kiss_twiddle_cpx *twiddles; michael@0: } kiss_fft_state; michael@0: michael@0: /*typedef struct kiss_fft_state* kiss_fft_cfg;*/ michael@0: michael@0: /** michael@0: * opus_fft_alloc michael@0: * michael@0: * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. michael@0: * michael@0: * typical usage: kiss_fft_cfg mycfg=opus_fft_alloc(1024,0,NULL,NULL); michael@0: * michael@0: * The return value from fft_alloc is a cfg buffer used internally michael@0: * by the fft routine or NULL. michael@0: * michael@0: * If lenmem is NULL, then opus_fft_alloc will allocate a cfg buffer using malloc. michael@0: * The returned value should be free()d when done to avoid memory leaks. michael@0: * michael@0: * The state can be placed in a user supplied buffer 'mem': michael@0: * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, michael@0: * then the function places the cfg in mem and the size used in *lenmem michael@0: * and returns mem. michael@0: * michael@0: * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), michael@0: * then the function returns NULL and places the minimum cfg michael@0: * buffer size in *lenmem. michael@0: * */ michael@0: michael@0: kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base); michael@0: michael@0: kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem); michael@0: michael@0: /** michael@0: * opus_fft(cfg,in_out_buf) michael@0: * michael@0: * Perform an FFT on a complex input buffer. michael@0: * for a forward FFT, michael@0: * fin should be f[0] , f[1] , ... ,f[nfft-1] michael@0: * fout will be F[0] , F[1] , ... ,F[nfft-1] michael@0: * Note that each element is complex and can be accessed like michael@0: f[k].r and f[k].i michael@0: * */ michael@0: void opus_fft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); michael@0: void opus_ifft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); michael@0: michael@0: void opus_fft_free(const kiss_fft_state *cfg); michael@0: michael@0: #ifdef __cplusplus michael@0: } michael@0: #endif michael@0: michael@0: #endif