annotate dsp/transforms/kissfft/_kiss_fft_guts.h @ 289:befe5aa6b450

* Refactor FFT a little bit so as to separate construction and processing rather than have a single static method -- will make it easier to use a different implementation * pull in KissFFT implementation (not hooked up yet)
author Chris Cannam <c.cannam@qmul.ac.uk>
date Wed, 13 May 2009 09:19:12 +0000
parents
children
rev   line source
c@289 1 /*
c@289 2 Copyright (c) 2003-2004, Mark Borgerding
c@289 3
c@289 4 All rights reserved.
c@289 5
c@289 6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
c@289 7
c@289 8 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
c@289 9 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
c@289 10 * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
c@289 11
c@289 12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
c@289 13 */
c@289 14
c@289 15 /* kiss_fft.h
c@289 16 defines kiss_fft_scalar as either short or a float type
c@289 17 and defines
c@289 18 typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
c@289 19 #include "kiss_fft.h"
c@289 20 #include <limits.h>
c@289 21
c@289 22 #define MAXFACTORS 32
c@289 23 /* e.g. an fft of length 128 has 4 factors
c@289 24 as far as kissfft is concerned
c@289 25 4*4*4*2
c@289 26 */
c@289 27
c@289 28 struct kiss_fft_state{
c@289 29 int nfft;
c@289 30 int inverse;
c@289 31 int factors[2*MAXFACTORS];
c@289 32 kiss_fft_cpx twiddles[1];
c@289 33 };
c@289 34
c@289 35 /*
c@289 36 Explanation of macros dealing with complex math:
c@289 37
c@289 38 C_MUL(m,a,b) : m = a*b
c@289 39 C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
c@289 40 C_SUB( res, a,b) : res = a - b
c@289 41 C_SUBFROM( res , a) : res -= a
c@289 42 C_ADDTO( res , a) : res += a
c@289 43 * */
c@289 44 #ifdef FIXED_POINT
c@289 45 #if (FIXED_POINT==32)
c@289 46 # define FRACBITS 31
c@289 47 # define SAMPPROD int64_t
c@289 48 #define SAMP_MAX 2147483647
c@289 49 #else
c@289 50 # define FRACBITS 15
c@289 51 # define SAMPPROD int32_t
c@289 52 #define SAMP_MAX 32767
c@289 53 #endif
c@289 54
c@289 55 #define SAMP_MIN -SAMP_MAX
c@289 56
c@289 57 #if defined(CHECK_OVERFLOW)
c@289 58 # define CHECK_OVERFLOW_OP(a,op,b) \
c@289 59 if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
c@289 60 fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); }
c@289 61 #endif
c@289 62
c@289 63
c@289 64 # define smul(a,b) ( (SAMPPROD)(a)*(b) )
c@289 65 # define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS )
c@289 66
c@289 67 # define S_MUL(a,b) sround( smul(a,b) )
c@289 68
c@289 69 # define C_MUL(m,a,b) \
c@289 70 do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
c@289 71 (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
c@289 72
c@289 73 # define DIVSCALAR(x,k) \
c@289 74 (x) = sround( smul( x, SAMP_MAX/k ) )
c@289 75
c@289 76 # define C_FIXDIV(c,div) \
c@289 77 do { DIVSCALAR( (c).r , div); \
c@289 78 DIVSCALAR( (c).i , div); }while (0)
c@289 79
c@289 80 # define C_MULBYSCALAR( c, s ) \
c@289 81 do{ (c).r = sround( smul( (c).r , s ) ) ;\
c@289 82 (c).i = sround( smul( (c).i , s ) ) ; }while(0)
c@289 83
c@289 84 #else /* not FIXED_POINT*/
c@289 85
c@289 86 # define S_MUL(a,b) ( (a)*(b) )
c@289 87 #define C_MUL(m,a,b) \
c@289 88 do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
c@289 89 (m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
c@289 90 # define C_FIXDIV(c,div) /* NOOP */
c@289 91 # define C_MULBYSCALAR( c, s ) \
c@289 92 do{ (c).r *= (s);\
c@289 93 (c).i *= (s); }while(0)
c@289 94 #endif
c@289 95
c@289 96 #ifndef CHECK_OVERFLOW_OP
c@289 97 # define CHECK_OVERFLOW_OP(a,op,b) /* noop */
c@289 98 #endif
c@289 99
c@289 100 #define C_ADD( res, a,b)\
c@289 101 do { \
c@289 102 CHECK_OVERFLOW_OP((a).r,+,(b).r)\
c@289 103 CHECK_OVERFLOW_OP((a).i,+,(b).i)\
c@289 104 (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
c@289 105 }while(0)
c@289 106 #define C_SUB( res, a,b)\
c@289 107 do { \
c@289 108 CHECK_OVERFLOW_OP((a).r,-,(b).r)\
c@289 109 CHECK_OVERFLOW_OP((a).i,-,(b).i)\
c@289 110 (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
c@289 111 }while(0)
c@289 112 #define C_ADDTO( res , a)\
c@289 113 do { \
c@289 114 CHECK_OVERFLOW_OP((res).r,+,(a).r)\
c@289 115 CHECK_OVERFLOW_OP((res).i,+,(a).i)\
c@289 116 (res).r += (a).r; (res).i += (a).i;\
c@289 117 }while(0)
c@289 118
c@289 119 #define C_SUBFROM( res , a)\
c@289 120 do {\
c@289 121 CHECK_OVERFLOW_OP((res).r,-,(a).r)\
c@289 122 CHECK_OVERFLOW_OP((res).i,-,(a).i)\
c@289 123 (res).r -= (a).r; (res).i -= (a).i; \
c@289 124 }while(0)
c@289 125
c@289 126
c@289 127 #ifdef FIXED_POINT
c@289 128 # define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase))
c@289 129 # define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase))
c@289 130 # define HALF_OF(x) ((x)>>1)
c@289 131 #elif defined(USE_SIMD)
c@289 132 # define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
c@289 133 # define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
c@289 134 # define HALF_OF(x) ((x)*_mm_set1_ps(.5))
c@289 135 #else
c@289 136 # define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
c@289 137 # define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
c@289 138 # define HALF_OF(x) ((x)*.5)
c@289 139 #endif
c@289 140
c@289 141 #define kf_cexp(x,phase) \
c@289 142 do{ \
c@289 143 (x)->r = KISS_FFT_COS(phase);\
c@289 144 (x)->i = KISS_FFT_SIN(phase);\
c@289 145 }while(0)
c@289 146
c@289 147
c@289 148 /* a debugging function */
c@289 149 #define pcpx(c)\
c@289 150 fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) )