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 | |