xref: /aosp_15_r20/external/speex/libspeexdsp/_kiss_fft_guts.h (revision 28e138c64d234588b5cd2a8a403b584bd3036e4e)
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