mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 04:50:29 -04:00 
			
		
		
		
	
		
			
	
	
		
			164 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			164 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | /*
 | ||
|  |  * codec2_fft.c | ||
|  |  * | ||
|  |  *  Created on: 24.09.2016 | ||
|  |  *      Author: danilo | ||
|  |  */ | ||
|  | 
 | ||
|  | #include "codec2_fft.h"
 | ||
|  | 
 | ||
|  | #ifdef USE_KISS_FFT
 | ||
|  | #include "_kiss_fft_guts.h"
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | namespace FreeDV | ||
|  | { | ||
|  | 
 | ||
|  | #ifdef USE_KISS_FFT
 | ||
|  | #else
 | ||
|  | #if 0
 | ||
|  | // caching constants in RAM did not seem to have an effect on performance
 | ||
|  | // TODO: Decide what to with this code
 | ||
|  | #define FFT_INIT_CACHE_SIZE 4
 | ||
|  | const arm_cfft_instance_f32* fft_init_cache[FFT_INIT_CACHE_SIZE]; | ||
|  | 
 | ||
|  | static const arm_cfft_instance_f32* arm_fft_instance2ram(const arm_cfft_instance_f32* in) | ||
|  | { | ||
|  | 
 | ||
|  |     arm_cfft_instance_f32* out = malloc(sizeof(arm_cfft_instance_f32)); | ||
|  | 
 | ||
|  |     if (out) { | ||
|  |         memcpy(out,in,sizeof(arm_cfft_instance_f32)); | ||
|  |         out->pBitRevTable = malloc(out->bitRevLength * sizeof(uint16_t)); | ||
|  |         out->pTwiddle = malloc(out->fftLen * sizeof(float32_t)); | ||
|  |         memcpy((void*)out->pBitRevTable,in->pBitRevTable,out->bitRevLength * sizeof(uint16_t)); | ||
|  |         memcpy((void*)out->pTwiddle,in->pTwiddle,out->fftLen * sizeof(float32_t)); | ||
|  |     } | ||
|  |     return out; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | static const arm_cfft_instance_f32* arm_fft_cache_get(const arm_cfft_instance_f32* romfft) | ||
|  | { | ||
|  |     const arm_cfft_instance_f32* retval = NULL; | ||
|  |     static int used = 0; | ||
|  |     for (int i = 0; fft_init_cache[i] != NULL && i < used; i++) | ||
|  |     { | ||
|  |         if (romfft->fftLen == fft_init_cache[i]->fftLen) | ||
|  |         { | ||
|  |             retval = fft_init_cache[i]; | ||
|  |             break; | ||
|  |         } | ||
|  |     } | ||
|  |     if (retval == NULL && used < FFT_INIT_CACHE_SIZE) | ||
|  |     { | ||
|  |          retval = arm_fft_instance2ram(romfft); | ||
|  |          fft_init_cache[used++] = retval; | ||
|  |     } | ||
|  |     if (retval == NULL) | ||
|  |     { | ||
|  |         retval = romfft; | ||
|  |     } | ||
|  |     return retval; | ||
|  | } | ||
|  | #endif
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | void codec2_fft_free(codec2_fft_cfg cfg) | ||
|  | { | ||
|  | #ifdef USE_KISS_FFT
 | ||
|  |     KISS_FFT_FREE(cfg); | ||
|  | #else
 | ||
|  |     FREE(cfg); | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | codec2_fft_cfg codec2_fft_alloc(int nfft, int inverse_fft, void* mem, std::size_t* lenmem) | ||
|  | { | ||
|  |     codec2_fft_cfg retval; | ||
|  | #ifdef USE_KISS_FFT
 | ||
|  |     retval = kiss_fft_alloc(nfft, inverse_fft, mem, lenmem); | ||
|  | #else
 | ||
|  |     retval = MALLOC(sizeof(codec2_fft_struct)); | ||
|  |     retval->inverse  = inverse_fft; | ||
|  |     switch(nfft) | ||
|  |     { | ||
|  |     case 128: | ||
|  |         retval->instance = &arm_cfft_sR_f32_len128; | ||
|  |         break; | ||
|  |     case 256: | ||
|  |         retval->instance = &arm_cfft_sR_f32_len256; | ||
|  |         break; | ||
|  |     case 512: | ||
|  |         retval->instance = &arm_cfft_sR_f32_len512; | ||
|  |         break; | ||
|  | //    case 1024:
 | ||
|  | //        retval->instance = &arm_cfft_sR_f32_len1024;
 | ||
|  | //        break;
 | ||
|  |     default: | ||
|  |         abort(); | ||
|  |     } | ||
|  |     // retval->instance = arm_fft_cache_get(retval->instance);
 | ||
|  | #endif
 | ||
|  |     return retval; | ||
|  | } | ||
|  | 
 | ||
|  | codec2_fftr_cfg codec2_fftr_alloc(int nfft, int inverse_fft, void* mem, std::size_t* lenmem) | ||
|  | { | ||
|  |     codec2_fftr_cfg retval; | ||
|  | #ifdef USE_KISS_FFT
 | ||
|  |     retval = kiss_fftr_alloc(nfft, inverse_fft, mem, lenmem); | ||
|  | #else
 | ||
|  |     retval = MALLOC(sizeof(codec2_fftr_struct)); | ||
|  |     retval->inverse  = inverse_fft; | ||
|  |     retval->instance = MALLOC(sizeof(arm_rfft_fast_instance_f32)); | ||
|  |     arm_rfft_fast_init_f32(retval->instance,nfft); | ||
|  |     // memcpy(&retval->instance->Sint,arm_fft_cache_get(&retval->instance->Sint),sizeof(arm_cfft_instance_f32));
 | ||
|  | #endif
 | ||
|  |     return retval; | ||
|  | } | ||
|  | void codec2_fftr_free(codec2_fftr_cfg cfg) | ||
|  | { | ||
|  | #ifdef USE_KISS_FFT
 | ||
|  |     KISS_FFT_FREE(cfg); | ||
|  | #else
 | ||
|  |     FREE(cfg->instance); | ||
|  |     FREE(cfg); | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | // there is a little overhead for inplace kiss_fft but this is
 | ||
|  | // on the powerful platforms like the Raspberry or even x86 PC based ones
 | ||
|  | // not noticeable
 | ||
|  | // the reduced usage of RAM and increased performance on STM32 platforms
 | ||
|  | // should be worth it.
 | ||
|  | void codec2_fft_inplace(codec2_fft_cfg cfg, codec2_fft_cpx* inout) | ||
|  | { | ||
|  | 
 | ||
|  | #ifdef USE_KISS_FFT
 | ||
|  |     kiss_fft_cpx in[512]; | ||
|  |     // decide whether to use the local stack based buffer for in
 | ||
|  |     // or to allow kiss_fft to allocate RAM
 | ||
|  |     // second part is just to play safe since first method
 | ||
|  |     // is much faster and uses less RAM
 | ||
|  |     if (cfg->nfft <= 512) | ||
|  |     { | ||
|  |         memcpy(in,inout,cfg->nfft*sizeof(kiss_fft_cpx)); | ||
|  |         kiss_fft(cfg, in, (kiss_fft_cpx*)inout); | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |         kiss_fft(cfg, (kiss_fft_cpx*)inout, (kiss_fft_cpx*)inout); | ||
|  |     } | ||
|  | #else
 | ||
|  |     arm_cfft_f32(cfg->instance,(float*)inout,cfg->inverse,1); | ||
|  |     if (cfg->inverse) | ||
|  |     { | ||
|  |         arm_scale_f32((float*)inout,cfg->instance->fftLen,(float*)inout,cfg->instance->fftLen*2); | ||
|  |     } | ||
|  | 
 | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | } // FreeDV
 |