BogaudioModules

BogaudioModules for VCV Rack
Log | Files | Refs | README | LICENSE

FFTRealFixLen.hpp (6158B)


      1 /*****************************************************************************
      2 
      3         FFTRealFixLen.hpp
      4         By Laurent de Soras
      5 
      6 --- Legal stuff ---
      7 
      8 This program is free software. It comes without any warranty, to
      9 the extent permitted by applicable law. You can redistribute it
     10 and/or modify it under the terms of the Do What The Fuck You Want
     11 To Public License, Version 2, as published by Sam Hocevar. See
     12 http://sam.zoy.org/wtfpl/COPYING for more details.
     13 
     14 *Tab=3***********************************************************************/
     15 
     16 
     17 
     18 #if defined (ffft_FFTRealFixLen_CURRENT_CODEHEADER)
     19 	#error Recursive inclusion of FFTRealFixLen code header.
     20 #endif
     21 #define	ffft_FFTRealFixLen_CURRENT_CODEHEADER
     22 
     23 #if ! defined (ffft_FFTRealFixLen_CODEHEADER_INCLUDED)
     24 #define	ffft_FFTRealFixLen_CODEHEADER_INCLUDED
     25 
     26 
     27 
     28 /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
     29 
     30 #include	"ffft/def.h"
     31 #include	"ffft/FFTRealPassDirect.h"
     32 #include	"ffft/FFTRealPassInverse.h"
     33 #include	"ffft/FFTRealSelect.h"
     34 
     35 #include	<cassert>
     36 #include	<cmath>
     37 
     38 namespace std { }
     39 
     40 
     41 
     42 namespace ffft
     43 {
     44 
     45 
     46 
     47 /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
     48 
     49 
     50 
     51 template <int LL2>
     52 FFTRealFixLen <LL2>::FFTRealFixLen ()
     53 :	_buffer (FFT_LEN)
     54 ,	_br_data (BR_ARR_SIZE)
     55 ,	_trigo_data (TRIGO_TABLE_ARR_SIZE)
     56 ,	_trigo_osc ()
     57 {
     58 	build_br_lut ();
     59 	build_trigo_lut ();
     60 	build_trigo_osc ();
     61 }
     62 
     63 
     64 
     65 template <int LL2>
     66 long	FFTRealFixLen <LL2>::get_length () const
     67 {
     68 	return (FFT_LEN);
     69 }
     70 
     71 
     72 
     73 // General case
     74 template <int LL2>
     75 void	FFTRealFixLen <LL2>::do_fft (DataType f [], const DataType x [])
     76 {
     77 	assert (f != 0);
     78 	assert (x != 0);
     79 	assert (x != f);
     80 	assert (FFT_LEN_L2 >= 3);
     81 
     82 	// Do the transform in several passes
     83 	const DataType	*	cos_ptr = &_trigo_data [0];
     84 	const long *	br_ptr = &_br_data [0];
     85 
     86 	FFTRealPassDirect <FFT_LEN_L2 - 1>::process (
     87 		FFT_LEN,
     88 		f,
     89 		&_buffer [0],
     90 		x,
     91 		cos_ptr,
     92 		TRIGO_TABLE_ARR_SIZE,
     93 		br_ptr,
     94 		&_trigo_osc [0]
     95 	);
     96 }
     97 
     98 // 4-point FFT
     99 template <>
    100 inline void	FFTRealFixLen <2>::do_fft (DataType f [], const DataType x [])
    101 {
    102 	assert (f != 0);
    103 	assert (x != 0);
    104 	assert (x != f);
    105 
    106 	f [1] = x [0] - x [2];
    107 	f [3] = x [1] - x [3];
    108 
    109 	const DataType	b_0 = x [0] + x [2];
    110 	const DataType	b_2 = x [1] + x [3];
    111 	
    112 	f [0] = b_0 + b_2;
    113 	f [2] = b_0 - b_2;
    114 }
    115 
    116 // 2-point FFT
    117 template <>
    118 inline void	FFTRealFixLen <1>::do_fft (DataType f [], const DataType x [])
    119 {
    120 	assert (f != 0);
    121 	assert (x != 0);
    122 	assert (x != f);
    123 
    124 	f [0] = x [0] + x [1];
    125 	f [1] = x [0] - x [1];
    126 }
    127 
    128 // 1-point FFT
    129 template <>
    130 inline void	FFTRealFixLen <0>::do_fft (DataType f [], const DataType x [])
    131 {
    132 	assert (f != 0);
    133 	assert (x != 0);
    134 
    135 	f [0] = x [0];
    136 }
    137 
    138 
    139 
    140 // General case
    141 template <int LL2>
    142 void	FFTRealFixLen <LL2>::do_ifft (const DataType f [], DataType x [])
    143 {
    144 	assert (f != 0);
    145 	assert (x != 0);
    146 	assert (x != f);
    147 	assert (FFT_LEN_L2 >= 3);
    148 
    149 	// Do the transform in several passes
    150 	DataType *		s_ptr =
    151 		FFTRealSelect <FFT_LEN_L2 & 1>::sel_bin (&_buffer [0], x);
    152 	DataType *		d_ptr =
    153 		FFTRealSelect <FFT_LEN_L2 & 1>::sel_bin (x, &_buffer [0]);
    154 	const DataType	*	cos_ptr = &_trigo_data [0];
    155 	const long *	br_ptr = &_br_data [0];
    156 
    157 	FFTRealPassInverse <FFT_LEN_L2 - 1>::process (
    158 		FFT_LEN,
    159 		d_ptr,
    160 		s_ptr,
    161 		f,
    162 		cos_ptr,
    163 		TRIGO_TABLE_ARR_SIZE,
    164 		br_ptr,
    165 		&_trigo_osc [0]
    166 	);
    167 }
    168 
    169 // 4-point IFFT
    170 template <>
    171 inline void	FFTRealFixLen <2>::do_ifft (const DataType f [], DataType x [])
    172 {
    173 	assert (f != 0);
    174 	assert (x != 0);
    175 	assert (x != f);
    176 
    177 	const DataType	b_0 = f [0] + f [2];
    178 	const DataType	b_2 = f [0] - f [2];
    179 
    180 	x [0] = b_0 + f [1] * 2;
    181 	x [2] = b_0 - f [1] * 2;
    182 	x [1] = b_2 + f [3] * 2;
    183 	x [3] = b_2 - f [3] * 2;
    184 }
    185 
    186 // 2-point IFFT
    187 template <>
    188 inline void	FFTRealFixLen <1>::do_ifft (const DataType f [], DataType x [])
    189 {
    190 	assert (f != 0);
    191 	assert (x != 0);
    192 	assert (x != f);
    193 
    194 	x [0] = f [0] + f [1];
    195 	x [1] = f [0] - f [1];
    196 }
    197 
    198 // 1-point IFFT
    199 template <>
    200 inline void	FFTRealFixLen <0>::do_ifft (const DataType f [], DataType x [])
    201 {
    202 	assert (f != 0);
    203 	assert (x != 0);
    204 	assert (x != f);
    205 
    206 	x [0] = f [0];
    207 }
    208 
    209 
    210 
    211 
    212 template <int LL2>
    213 void	FFTRealFixLen <LL2>::rescale (DataType x []) const
    214 {
    215 	assert (x != 0);
    216 
    217 	const DataType	mul = DataType (1.0 / FFT_LEN);
    218 
    219 	if (FFT_LEN < 4)
    220 	{
    221 		long				i = FFT_LEN - 1;
    222 		do
    223 		{
    224 			x [i] *= mul;
    225 			--i;
    226 		}
    227 		while (i >= 0);
    228 	}
    229 
    230 	else
    231 	{
    232 		assert ((FFT_LEN & 3) == 0);
    233 
    234 		// Could be optimized with SIMD instruction sets (needs alignment check)
    235 		long				i = FFT_LEN - 4;
    236 		do
    237 		{
    238 			x [i + 0] *= mul;
    239 			x [i + 1] *= mul;
    240 			x [i + 2] *= mul;
    241 			x [i + 3] *= mul;
    242 			i -= 4;
    243 		}
    244 		while (i >= 0);
    245 	}
    246 }
    247 
    248 
    249 
    250 /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
    251 
    252 
    253 
    254 /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
    255 
    256 
    257 
    258 template <int LL2>
    259 void	FFTRealFixLen <LL2>::build_br_lut ()
    260 {
    261 	_br_data [0] = 0;
    262 	for (long cnt = 1; cnt < BR_ARR_SIZE; ++cnt)
    263 	{
    264 		long				index = cnt << 2;
    265 		long				br_index = 0;
    266 
    267 		int				bit_cnt = FFT_LEN_L2;
    268 		do
    269 		{
    270 			br_index <<= 1;
    271 			br_index += (index & 1);
    272 			index >>= 1;
    273 
    274 			-- bit_cnt;
    275 		}
    276 		while (bit_cnt > 0);
    277 
    278 		_br_data [cnt] = br_index;
    279 	}
    280 }
    281 
    282 
    283 
    284 template <int LL2>
    285 void	FFTRealFixLen <LL2>::build_trigo_lut ()
    286 {
    287 	const double	mul = (0.5 * PI) / TRIGO_TABLE_ARR_SIZE;
    288 	for (long i = 0; i < TRIGO_TABLE_ARR_SIZE; ++ i)
    289 	{
    290 		using namespace std;
    291 
    292 		_trigo_data [i] = DataType (cos (i * mul));
    293 	}
    294 }
    295 
    296 
    297 
    298 template <int LL2>
    299 void	FFTRealFixLen <LL2>::build_trigo_osc ()
    300 {
    301 	for (int i = 0; i < NBR_TRIGO_OSC; ++i)
    302 	{
    303 		OscType &		osc = _trigo_osc [i];
    304 
    305 		const long		len = static_cast <long> (TRIGO_TABLE_ARR_SIZE) << (i + 1);
    306 		const double	mul = (0.5 * PI) / len;
    307 		osc.set_step (mul);
    308 	}
    309 }
    310 
    311 
    312 
    313 }	// namespace ffft
    314 
    315 
    316 
    317 #endif	// ffft_FFTRealFixLen_CODEHEADER_INCLUDED
    318 
    319 #undef ffft_FFTRealFixLen_CURRENT_CODEHEADER
    320 
    321 
    322 
    323 /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/