mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-04 05:30:32 -05: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
							 |