1*28e138c6SAndroid Build Coastguard Worker /* 2*28e138c6SAndroid Build Coastguard Worker Copyright (c) 2003-2004, Mark Borgerding 3*28e138c6SAndroid Build Coastguard Worker 4*28e138c6SAndroid Build Coastguard Worker All rights reserved. 5*28e138c6SAndroid Build Coastguard Worker 6*28e138c6SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7*28e138c6SAndroid Build Coastguard Worker 8*28e138c6SAndroid Build Coastguard Worker * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9*28e138c6SAndroid Build Coastguard Worker * 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. 10*28e138c6SAndroid Build Coastguard Worker * 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. 11*28e138c6SAndroid Build Coastguard Worker 12*28e138c6SAndroid Build Coastguard Worker 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. 13*28e138c6SAndroid Build Coastguard Worker */ 14*28e138c6SAndroid Build Coastguard Worker 15*28e138c6SAndroid Build Coastguard Worker #define MIN(a,b) ((a)<(b) ? (a):(b)) 16*28e138c6SAndroid Build Coastguard Worker #define MAX(a,b) ((a)>(b) ? (a):(b)) 17*28e138c6SAndroid Build Coastguard Worker 18*28e138c6SAndroid Build Coastguard Worker /* kiss_fft.h 19*28e138c6SAndroid Build Coastguard Worker defines kiss_fft_scalar as either short or a float type 20*28e138c6SAndroid Build Coastguard Worker and defines 21*28e138c6SAndroid Build Coastguard Worker typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ 22*28e138c6SAndroid Build Coastguard Worker #include "kiss_fft.h" 23*28e138c6SAndroid Build Coastguard Worker #include "math_approx.h" 24*28e138c6SAndroid Build Coastguard Worker 25*28e138c6SAndroid Build Coastguard Worker #define MAXFACTORS 32 26*28e138c6SAndroid Build Coastguard Worker /* e.g. an fft of length 128 has 4 factors 27*28e138c6SAndroid Build Coastguard Worker as far as kissfft is concerned 28*28e138c6SAndroid Build Coastguard Worker 4*4*4*2 29*28e138c6SAndroid Build Coastguard Worker */ 30*28e138c6SAndroid Build Coastguard Worker 31*28e138c6SAndroid Build Coastguard Worker struct kiss_fft_state{ 32*28e138c6SAndroid Build Coastguard Worker int nfft; 33*28e138c6SAndroid Build Coastguard Worker int inverse; 34*28e138c6SAndroid Build Coastguard Worker int factors[2*MAXFACTORS]; 35*28e138c6SAndroid Build Coastguard Worker kiss_fft_cpx twiddles[1]; 36*28e138c6SAndroid Build Coastguard Worker }; 37*28e138c6SAndroid Build Coastguard Worker 38*28e138c6SAndroid Build Coastguard Worker /* 39*28e138c6SAndroid Build Coastguard Worker Explanation of macros dealing with complex math: 40*28e138c6SAndroid Build Coastguard Worker 41*28e138c6SAndroid Build Coastguard Worker C_MUL(m,a,b) : m = a*b 42*28e138c6SAndroid Build Coastguard Worker C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise 43*28e138c6SAndroid Build Coastguard Worker C_SUB( res, a,b) : res = a - b 44*28e138c6SAndroid Build Coastguard Worker C_SUBFROM( res , a) : res -= a 45*28e138c6SAndroid Build Coastguard Worker C_ADDTO( res , a) : res += a 46*28e138c6SAndroid Build Coastguard Worker * */ 47*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT 48*28e138c6SAndroid Build Coastguard Worker #include "arch.h" 49*28e138c6SAndroid Build Coastguard Worker # define FRACBITS 15 50*28e138c6SAndroid Build Coastguard Worker # define SAMPPROD spx_int32_t 51*28e138c6SAndroid Build Coastguard Worker #define SAMP_MAX 32767 52*28e138c6SAndroid Build Coastguard Worker 53*28e138c6SAndroid Build Coastguard Worker #define SAMP_MIN -SAMP_MAX 54*28e138c6SAndroid Build Coastguard Worker 55*28e138c6SAndroid Build Coastguard Worker #if defined(CHECK_OVERFLOW) 56*28e138c6SAndroid Build Coastguard Worker # define CHECK_OVERFLOW_OP(a,op,b) \ 57*28e138c6SAndroid Build Coastguard Worker if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ 58*28e138c6SAndroid Build Coastguard Worker fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } 59*28e138c6SAndroid Build Coastguard Worker #endif 60*28e138c6SAndroid Build Coastguard Worker 61*28e138c6SAndroid Build Coastguard Worker 62*28e138c6SAndroid Build Coastguard Worker # define smul(a,b) ( (SAMPPROD)(a)*(b) ) 63*28e138c6SAndroid Build Coastguard Worker # define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) 64*28e138c6SAndroid Build Coastguard Worker 65*28e138c6SAndroid Build Coastguard Worker # define S_MUL(a,b) sround( smul(a,b) ) 66*28e138c6SAndroid Build Coastguard Worker 67*28e138c6SAndroid Build Coastguard Worker # define C_MUL(m,a,b) \ 68*28e138c6SAndroid Build Coastguard Worker do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ 69*28e138c6SAndroid Build Coastguard Worker (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) 70*28e138c6SAndroid Build Coastguard Worker 71*28e138c6SAndroid Build Coastguard Worker # define C_MUL4(m,a,b) \ 72*28e138c6SAndroid Build Coastguard Worker do{ (m).r = PSHR32( smul((a).r,(b).r) - smul((a).i,(b).i),17 ); \ 73*28e138c6SAndroid Build Coastguard Worker (m).i = PSHR32( smul((a).r,(b).i) + smul((a).i,(b).r),17 ); }while(0) 74*28e138c6SAndroid Build Coastguard Worker 75*28e138c6SAndroid Build Coastguard Worker # define DIVSCALAR(x,k) \ 76*28e138c6SAndroid Build Coastguard Worker (x) = sround( smul( x, SAMP_MAX/k ) ) 77*28e138c6SAndroid Build Coastguard Worker 78*28e138c6SAndroid Build Coastguard Worker # define C_FIXDIV(c,div) \ 79*28e138c6SAndroid Build Coastguard Worker do { DIVSCALAR( (c).r , div); \ 80*28e138c6SAndroid Build Coastguard Worker DIVSCALAR( (c).i , div); }while (0) 81*28e138c6SAndroid Build Coastguard Worker 82*28e138c6SAndroid Build Coastguard Worker # define C_MULBYSCALAR( c, s ) \ 83*28e138c6SAndroid Build Coastguard Worker do{ (c).r = sround( smul( (c).r , s ) ) ;\ 84*28e138c6SAndroid Build Coastguard Worker (c).i = sround( smul( (c).i , s ) ) ; }while(0) 85*28e138c6SAndroid Build Coastguard Worker 86*28e138c6SAndroid Build Coastguard Worker #else /* not FIXED_POINT*/ 87*28e138c6SAndroid Build Coastguard Worker 88*28e138c6SAndroid Build Coastguard Worker # define S_MUL(a,b) ( (a)*(b) ) 89*28e138c6SAndroid Build Coastguard Worker #define C_MUL(m,a,b) \ 90*28e138c6SAndroid Build Coastguard Worker do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ 91*28e138c6SAndroid Build Coastguard Worker (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) 92*28e138c6SAndroid Build Coastguard Worker 93*28e138c6SAndroid Build Coastguard Worker #define C_MUL4(m,a,b) C_MUL(m,a,b) 94*28e138c6SAndroid Build Coastguard Worker 95*28e138c6SAndroid Build Coastguard Worker # define C_FIXDIV(c,div) /* NOOP */ 96*28e138c6SAndroid Build Coastguard Worker # define C_MULBYSCALAR( c, s ) \ 97*28e138c6SAndroid Build Coastguard Worker do{ (c).r *= (s);\ 98*28e138c6SAndroid Build Coastguard Worker (c).i *= (s); }while(0) 99*28e138c6SAndroid Build Coastguard Worker #endif 100*28e138c6SAndroid Build Coastguard Worker 101*28e138c6SAndroid Build Coastguard Worker #ifndef CHECK_OVERFLOW_OP 102*28e138c6SAndroid Build Coastguard Worker # define CHECK_OVERFLOW_OP(a,op,b) /* noop */ 103*28e138c6SAndroid Build Coastguard Worker #endif 104*28e138c6SAndroid Build Coastguard Worker 105*28e138c6SAndroid Build Coastguard Worker #define C_ADD( res, a,b)\ 106*28e138c6SAndroid Build Coastguard Worker do { \ 107*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP((a).r,+,(b).r)\ 108*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP((a).i,+,(b).i)\ 109*28e138c6SAndroid Build Coastguard Worker (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ 110*28e138c6SAndroid Build Coastguard Worker }while(0) 111*28e138c6SAndroid Build Coastguard Worker #define C_SUB( res, a,b)\ 112*28e138c6SAndroid Build Coastguard Worker do { \ 113*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP((a).r,-,(b).r)\ 114*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP((a).i,-,(b).i)\ 115*28e138c6SAndroid Build Coastguard Worker (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ 116*28e138c6SAndroid Build Coastguard Worker }while(0) 117*28e138c6SAndroid Build Coastguard Worker #define C_ADDTO( res , a)\ 118*28e138c6SAndroid Build Coastguard Worker do { \ 119*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP((res).r,+,(a).r)\ 120*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP((res).i,+,(a).i)\ 121*28e138c6SAndroid Build Coastguard Worker (res).r += (a).r; (res).i += (a).i;\ 122*28e138c6SAndroid Build Coastguard Worker }while(0) 123*28e138c6SAndroid Build Coastguard Worker 124*28e138c6SAndroid Build Coastguard Worker #define C_SUBFROM( res , a)\ 125*28e138c6SAndroid Build Coastguard Worker do {\ 126*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP((res).r,-,(a).r)\ 127*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP((res).i,-,(a).i)\ 128*28e138c6SAndroid Build Coastguard Worker (res).r -= (a).r; (res).i -= (a).i; \ 129*28e138c6SAndroid Build Coastguard Worker }while(0) 130*28e138c6SAndroid Build Coastguard Worker 131*28e138c6SAndroid Build Coastguard Worker 132*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT 133*28e138c6SAndroid Build Coastguard Worker # define KISS_FFT_COS(phase) floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase)))) 134*28e138c6SAndroid Build Coastguard Worker # define KISS_FFT_SIN(phase) floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase)))) 135*28e138c6SAndroid Build Coastguard Worker # define HALF_OF(x) ((x)>>1) 136*28e138c6SAndroid Build Coastguard Worker #elif defined(USE_SIMD) 137*28e138c6SAndroid Build Coastguard Worker # define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) ) 138*28e138c6SAndroid Build Coastguard Worker # define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) ) 139*28e138c6SAndroid Build Coastguard Worker # define HALF_OF(x) ((x)*_mm_set1_ps(.5)) 140*28e138c6SAndroid Build Coastguard Worker #else 141*28e138c6SAndroid Build Coastguard Worker # define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) 142*28e138c6SAndroid Build Coastguard Worker # define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) 143*28e138c6SAndroid Build Coastguard Worker # define HALF_OF(x) ((x)*.5) 144*28e138c6SAndroid Build Coastguard Worker #endif 145*28e138c6SAndroid Build Coastguard Worker 146*28e138c6SAndroid Build Coastguard Worker #define kf_cexp(x,phase) \ 147*28e138c6SAndroid Build Coastguard Worker do{ \ 148*28e138c6SAndroid Build Coastguard Worker (x)->r = KISS_FFT_COS(phase);\ 149*28e138c6SAndroid Build Coastguard Worker (x)->i = KISS_FFT_SIN(phase);\ 150*28e138c6SAndroid Build Coastguard Worker }while(0) 151*28e138c6SAndroid Build Coastguard Worker #define kf_cexp2(x,phase) \ 152*28e138c6SAndroid Build Coastguard Worker do{ \ 153*28e138c6SAndroid Build Coastguard Worker (x)->r = spx_cos_norm((phase));\ 154*28e138c6SAndroid Build Coastguard Worker (x)->i = spx_cos_norm((phase)-32768);\ 155*28e138c6SAndroid Build Coastguard Worker }while(0) 156*28e138c6SAndroid Build Coastguard Worker 157*28e138c6SAndroid Build Coastguard Worker 158*28e138c6SAndroid Build Coastguard Worker /* a debugging function */ 159*28e138c6SAndroid Build Coastguard Worker #define pcpx(c)\ 160*28e138c6SAndroid Build Coastguard Worker fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) 161