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