#ifndef __EEL_FFT_H_ #define __EEL_FFT_H_ #include "../fft.h" #if WDL_FFT_REALSIZE != EEL_F_SIZE #error WDL_FFT_REALSIZE -- EEL_F_SIZE size mismatch #endif #ifndef EEL_FFT_MINBITLEN #define EEL_FFT_MINBITLEN 4 #endif #ifndef EEL_FFT_MAXBITLEN #define EEL_FFT_MAXBITLEN 15 #endif #ifndef EEL_FFT_MINBITLEN_REORDER #define EEL_FFT_MINBITLEN_REORDER (EEL_FFT_MINBITLEN-1) #endif //#define EEL_SUPER_FAST_FFT_REORDERING // quite a bit faster (50-100%) than "normal", but uses a 256kb lookup //#define EEL_SLOW_FFT_REORDERING // 20%-80% slower than normal, alloca() use, no reason to ever use this #ifdef EEL_SUPER_FAST_FFT_REORDERING static int *fft_reorder_table_for_bitsize(int bitsz) { static int s_tab[ (2 << EEL_FFT_MAXBITLEN) + 24*(EEL_FFT_MAXBITLEN-EEL_FFT_MINBITLEN_REORDER+1) ]; // big 256kb table, ugh if (bitsz<=EEL_FFT_MINBITLEN_REORDER) return s_tab; return s_tab + (1<= 4 && dir < 8) { if (dir == 4 || dir == 5) { //timingEnter(0); #if defined(EEL_SUPER_FAST_FFT_REORDERING) || !defined(EEL_SLOW_FFT_REORDERING) fft_reorder_buffer(sizebits,(WDL_FFT_COMPLEX*)data,dir==4); #else // old blech const int flen=1<= 0 && dir < 2) { WDL_fft((WDL_FFT_COMPLEX*)data,1<= 2 && dir < 4) { WDL_real_fft((WDL_FFT_REAL*)data,1<1 && bitl < EEL_FFT_MAXBITLEN) { bitl++; l>>=1; } if (bitl < ((dir&4) ? EEL_FFT_MINBITLEN_REORDER : EEL_FFT_MINBITLEN)) // smallest FFT is 16 item, smallest reorder is 8 item { return start; } ilen=1< NSEEL_RAM_ITEMSPERBLOCK || dest_offs < 0 || src_offs < 0 || dest_offs >= NSEEL_RAM_BLOCKS*NSEEL_RAM_ITEMSPERBLOCK || src_offs >= NSEEL_RAM_BLOCKS*NSEEL_RAM_ITEMSPERBLOCK) return dest; if ((dest_offs&(NSEEL_RAM_ITEMSPERBLOCK-1)) + len > NSEEL_RAM_ITEMSPERBLOCK) return dest; if ((src_offs&(NSEEL_RAM_ITEMSPERBLOCK-1)) + len > NSEEL_RAM_ITEMSPERBLOCK) return dest; srcptr = __NSEEL_RAMAlloc(blocks,src_offs); if (!srcptr || srcptr==&nseel_ramalloc_onfail) return dest; destptr = __NSEEL_RAMAlloc(blocks,dest_offs); if (!destptr || destptr==&nseel_ramalloc_onfail) return dest; WDL_fft_complexmul((WDL_FFT_COMPLEX*)destptr,(WDL_FFT_COMPLEX*)srcptr,(len/2)&~1); return dest; } void EEL_fft_register() { WDL_fft_init(); #if defined(EEL_SUPER_FAST_FFT_REORDERING) if (!fft_reorder_table_for_bitsize(EEL_FFT_MINBITLEN_REORDER)[0]) { int x; for (x=EEL_FFT_MINBITLEN_REORDER;x<=EEL_FFT_MAXBITLEN;x++) fft_make_reorder_table(x,fft_reorder_table_for_bitsize(x)); } #endif NSEEL_addfunc_retptr("convolve_c",3,NSEEL_PProc_RAM,&eel_convolve_c); NSEEL_addfunc_retptr("fft",2,NSEEL_PProc_RAM,&eel_fft); NSEEL_addfunc_retptr("ifft",2,NSEEL_PProc_RAM,&eel_ifft); NSEEL_addfunc_retptr("fft_real",2,NSEEL_PProc_RAM,&eel_fft_real); NSEEL_addfunc_retptr("ifft_real",2,NSEEL_PProc_RAM,&eel_ifft_real); NSEEL_addfunc_retptr("fft_permute",2,NSEEL_PProc_RAM,&eel_fft_permute); NSEEL_addfunc_retptr("fft_ipermute",2,NSEEL_PProc_RAM,&eel_ifft_permute); } #ifdef EEL_WANT_DOCUMENTATION static const char *eel_fft_function_reference = "convolve_c\tdest,src,size\tMultiplies each of size complex pairs in dest by the complex pairs in src. Often used for convolution.\0" "fft\tbuffer,size\tPerforms a FFT on the data in the local memory buffer at the offset specified by the first parameter. The size of the FFT is specified " "by the second parameter, which must be 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, or 32768. The outputs are permuted, so if " "you plan to use them in-order, call fft_permute(buffer, size) before and fft_ipermute(buffer,size) after your in-order use. Your inputs or " "outputs will need to be scaled down by 1/size, if used.\n" "Note that fft()/ifft() require real / imaginary input pairs, so a 256 point FFT actually works with 512 items.\n" "Note that fft()/ifft() must NOT cross a 65,536 item boundary, so be sure to specify the offset accordingly.\0" "ifft\tbuffer,size\tPerform an inverse FFT. For more information see fft().\0" "fft_real\tbuffer,size\tPerforms an FFT, but takes size input samples and produces size/2 complex output pairs. Usually used along with fft_permute(size/2). Inputs/outputs will need to be scaled by 0.5/size.\0" "ifft_real\tbuffer,size\tPerforms an inverse FFT, but takes size/2 complex input pairs and produces size real output values. Usually used along with fft_ipermute(size/2).\0" "fft_permute\tbuffer,size\tPermute the output of fft() to have bands in-order. See fft() for more information.\0" "fft_ipermute\tbuffer,size\tPermute the input for ifft(), taking bands from in-order to the order ifft() requires. See fft() for more information.\0" ; #endif #endif