1 /* 2 * Copyright (c) 2003-2010, Mark Borgerding. All rights reserved. 3 * This file is part of KISS FFT - https://github.com/mborgerding/kissfft 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 * See COPYING file for more information. 7 */ 8 9 /* kiss_fft.h 10 defines kiss_fft_scalar as either short or a float type 11 and defines 12 typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ 13 14 #ifndef _kiss_fft_guts_h 15 #define _kiss_fft_guts_h 16 17 #include "kiss_fft.h" 18 #include "kiss_fft_log.h" 19 #include <limits.h> 20 21 #define MAXFACTORS 32 22 /* e.g. an fft of length 128 has 4 factors 23 as far as kissfft is concerned 24 4*4*4*2 25 */ 26 27 struct kiss_fft_state{ 28 int nfft; 29 int inverse; 30 int factors[2*MAXFACTORS]; 31 kiss_fft_cpx twiddles[1]; 32 }; 33 34 /* 35 Explanation of macros dealing with complex math: 36 37 C_MUL(m,a,b) : m = a*b 38 C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise 39 C_SUB( res, a,b) : res = a - b 40 C_SUBFROM( res , a) : res -= a 41 C_ADDTO( res , a) : res += a 42 * */ 43 #ifdef FIXED_POINT 44 #include <stdint.h> 45 #if (FIXED_POINT==32) 46 # define FRACBITS 31 47 # define SAMPPROD int64_t 48 #define SAMP_MAX INT32_MAX 49 #define SAMP_MIN INT32_MIN 50 #else 51 # define FRACBITS 15 52 # define SAMPPROD int32_t 53 #define SAMP_MAX INT16_MAX 54 #define SAMP_MIN INT16_MIN 55 #endif 56 57 #if defined(CHECK_OVERFLOW) 58 # define CHECK_OVERFLOW_OP(a,op,b) \ 59 if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ 60 KISS_FFT_WARNING("overflow (%d " #op" %d) = %ld", (a),(b),(SAMPPROD)(a) op (SAMPPROD)(b)); } 61 #endif 62 63 64 # define smul(a,b) ( (SAMPPROD)(a)*(b) ) 65 # define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) 66 67 # define S_MUL(a,b) sround( smul(a,b) ) 68 69 # define C_MUL(m,a,b) \ 70 do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ 71 (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) 72 73 # define DIVSCALAR(x,k) \ 74 (x) = sround( smul( x, SAMP_MAX/k ) ) 75 76 # define C_FIXDIV(c,div) \ 77 do { DIVSCALAR( (c).r , div); \ 78 DIVSCALAR( (c).i , div); }while (0) 79 80 # define C_MULBYSCALAR( c, s ) \ 81 do{ (c).r = sround( smul( (c).r , s ) ) ;\ 82 (c).i = sround( smul( (c).i , s ) ) ; }while(0) 83 84 #else /* not FIXED_POINT*/ 85 86 # define S_MUL(a,b) ( (a)*(b) ) 87 #define C_MUL(m,a,b) \ 88 do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ 89 (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) 90 # define C_FIXDIV(c,div) /* NOOP */ 91 # define C_MULBYSCALAR( c, s ) \ 92 do{ (c).r *= (s);\ 93 (c).i *= (s); }while(0) 94 #endif 95 96 #ifndef CHECK_OVERFLOW_OP 97 # define CHECK_OVERFLOW_OP(a,op,b) /* noop */ 98 #endif 99 100 #define C_ADD( res, a,b)\ 101 do { \ 102 CHECK_OVERFLOW_OP((a).r,+,(b).r)\ 103 CHECK_OVERFLOW_OP((a).i,+,(b).i)\ 104 (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ 105 }while(0) 106 #define C_SUB( res, a,b)\ 107 do { \ 108 CHECK_OVERFLOW_OP((a).r,-,(b).r)\ 109 CHECK_OVERFLOW_OP((a).i,-,(b).i)\ 110 (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ 111 }while(0) 112 #define C_ADDTO( res , a)\ 113 do { \ 114 CHECK_OVERFLOW_OP((res).r,+,(a).r)\ 115 CHECK_OVERFLOW_OP((res).i,+,(a).i)\ 116 (res).r += (a).r; (res).i += (a).i;\ 117 }while(0) 118 119 #define C_SUBFROM( res , a)\ 120 do {\ 121 CHECK_OVERFLOW_OP((res).r,-,(a).r)\ 122 CHECK_OVERFLOW_OP((res).i,-,(a).i)\ 123 (res).r -= (a).r; (res).i -= (a).i; \ 124 }while(0) 125 126 127 #ifdef FIXED_POINT 128 # define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase)) 129 # define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase)) 130 # define HALF_OF(x) ((x)>>1) 131 #elif defined(USE_SIMD) 132 # define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) ) 133 # define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) ) 134 # define HALF_OF(x) ((x)*_mm_set1_ps(.5)) 135 #else 136 # define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) 137 # define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) 138 # define HALF_OF(x) ((x)*((kiss_fft_scalar).5)) 139 #endif 140 141 #define kf_cexp(x,phase) \ 142 do{ \ 143 (x)->r = KISS_FFT_COS(phase);\ 144 (x)->i = KISS_FFT_SIN(phase);\ 145 }while(0) 146 147 148 /* a debugging function */ 149 #define pcpx(c)\ 150 KISS_FFT_DEBUG("%g + %gi\n",(double)((c)->r),(double)((c)->i)) 151 152 153 #ifdef KISS_FFT_USE_ALLOCA 154 // define this to allow use of alloca instead of malloc for temporary buffers 155 // Temporary buffers are used in two case: 156 // 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5 157 // 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform. 158 #include <alloca.h> 159 #define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes) 160 #define KISS_FFT_TMP_FREE(ptr) 161 #else 162 #define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes) 163 #define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr) 164 #endif 165 166 #endif /* _kiss_fft_guts_h */ 167 168