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