mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 13:11:20 -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
 |