GNU Radio 3.6.5 C++ API
|
00001 /* 00002 Copyright (c) 2003-2010, Mark Borgerding 00003 00004 All rights reserved. 00005 00006 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 00009 * 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. 00010 * 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. 00011 00012 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. 00013 */ 00014 00015 /* kiss_fft.h 00016 defines kiss_fft_scalar as either short or a float type 00017 and defines 00018 typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ 00019 #include "kiss_fft.h" 00020 #include <limits.h> 00021 00022 #define MAXFACTORS 32 00023 /* e.g. an fft of length 128 has 4 factors 00024 as far as kissfft is concerned 00025 4*4*4*2 00026 */ 00027 00028 struct kiss_fft_state{ 00029 int nfft; 00030 int inverse; 00031 int factors[2*MAXFACTORS]; 00032 kiss_fft_cpx twiddles[1]; 00033 }; 00034 00035 /* 00036 Explanation of macros dealing with complex math: 00037 00038 C_MUL(m,a,b) : m = a*b 00039 C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise 00040 C_SUB( res, a,b) : res = a - b 00041 C_SUBFROM( res , a) : res -= a 00042 C_ADDTO( res , a) : res += a 00043 * */ 00044 #ifdef FIXED_POINT 00045 #if (FIXED_POINT==32) 00046 # define FRACBITS 31 00047 # define SAMPPROD int64_t 00048 #define SAMP_MAX 2147483647 00049 #else 00050 # define FRACBITS 15 00051 # define SAMPPROD int32_t 00052 #define SAMP_MAX 32767 00053 #endif 00054 00055 #define SAMP_MIN -SAMP_MAX 00056 00057 #if defined(CHECK_OVERFLOW) 00058 # define CHECK_OVERFLOW_OP(a,op,b) \ 00059 if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ 00060 fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } 00061 #endif 00062 00063 00064 # define smul(a,b) ( (SAMPPROD)(a)*(b) ) 00065 # define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) 00066 00067 # define S_MUL(a,b) sround( smul(a,b) ) 00068 00069 # define C_MUL(m,a,b) \ 00070 do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ 00071 (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) 00072 00073 # define DIVSCALAR(x,k) \ 00074 (x) = sround( smul( x, SAMP_MAX/k ) ) 00075 00076 # define C_FIXDIV(c,div) \ 00077 do { DIVSCALAR( (c).r , div); \ 00078 DIVSCALAR( (c).i , div); }while (0) 00079 00080 # define C_MULBYSCALAR( c, s ) \ 00081 do{ (c).r = sround( smul( (c).r , s ) ) ;\ 00082 (c).i = sround( smul( (c).i , s ) ) ; }while(0) 00083 00084 #else /* not FIXED_POINT*/ 00085 00086 # define S_MUL(a,b) ( (a)*(b) ) 00087 #define C_MUL(m,a,b) \ 00088 do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ 00089 (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) 00090 # define C_FIXDIV(c,div) /* NOOP */ 00091 # define C_MULBYSCALAR( c, s ) \ 00092 do{ (c).r *= (s);\ 00093 (c).i *= (s); }while(0) 00094 #endif 00095 00096 #ifndef CHECK_OVERFLOW_OP 00097 # define CHECK_OVERFLOW_OP(a,op,b) /* noop */ 00098 #endif 00099 00100 #define C_ADD( res, a,b)\ 00101 do { \ 00102 CHECK_OVERFLOW_OP((a).r,+,(b).r)\ 00103 CHECK_OVERFLOW_OP((a).i,+,(b).i)\ 00104 (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ 00105 }while(0) 00106 #define C_SUB( res, a,b)\ 00107 do { \ 00108 CHECK_OVERFLOW_OP((a).r,-,(b).r)\ 00109 CHECK_OVERFLOW_OP((a).i,-,(b).i)\ 00110 (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ 00111 }while(0) 00112 #define C_ADDTO( res , a)\ 00113 do { \ 00114 CHECK_OVERFLOW_OP((res).r,+,(a).r)\ 00115 CHECK_OVERFLOW_OP((res).i,+,(a).i)\ 00116 (res).r += (a).r; (res).i += (a).i;\ 00117 }while(0) 00118 00119 #define C_SUBFROM( res , a)\ 00120 do {\ 00121 CHECK_OVERFLOW_OP((res).r,-,(a).r)\ 00122 CHECK_OVERFLOW_OP((res).i,-,(a).i)\ 00123 (res).r -= (a).r; (res).i -= (a).i; \ 00124 }while(0) 00125 00126 00127 #ifdef FIXED_POINT 00128 # define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase)) 00129 # define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase)) 00130 # define HALF_OF(x) ((x)>>1) 00131 #elif defined(USE_SIMD) 00132 # define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) ) 00133 # define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) ) 00134 # define HALF_OF(x) ((x)*_mm_set1_ps(.5)) 00135 #else 00136 # define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) 00137 # define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) 00138 # define HALF_OF(x) ((x)*.5) 00139 #endif 00140 00141 #define kf_cexp(x,phase) \ 00142 do{ \ 00143 (x)->r = KISS_FFT_COS(phase);\ 00144 (x)->i = KISS_FFT_SIN(phase);\ 00145 }while(0) 00146 00147 00148 /* a debugging function */ 00149 #define pcpx(c)\ 00150 fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) 00151 00152 00153 #ifdef KISS_FFT_USE_ALLOCA 00154 // define this to allow use of alloca instead of malloc for temporary buffers 00155 // Temporary buffers are used in two case: 00156 // 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5 00157 // 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform. 00158 #include <alloca.h> 00159 #define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes) 00160 #define KISS_FFT_TMP_FREE(ptr) 00161 #else 00162 #define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes) 00163 #define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr) 00164 #endif