fractional_decimator_ff gets new algorithm based on Lagrange interpolator formula
This commit is contained in:
parent
1339352da7
commit
f4da40ffa7
5 changed files with 957 additions and 743 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,3 +5,4 @@ ddcd
|
|||
*.so
|
||||
tags
|
||||
dumpvect.*.vect
|
||||
grc_tests/top_block.py
|
||||
|
|
48
csdr.c
48
csdr.c
|
@ -97,6 +97,7 @@ char usage[]=
|
|||
" agc_ff [hang_time [reference [attack_rate [decay_rate [max_gain [attack_wait [filter_alpha]]]]]]]\n"
|
||||
" fastagc_ff [block_size [reference]]\n"
|
||||
" rational_resampler_ff <interpolation> <decimation> [transition_bw [window]]\n"
|
||||
" old_fractional_decimator_ff <decimation_rate> [transition_bw [window]]\n"
|
||||
" fractional_decimator_ff <decimation_rate> [transition_bw [window]]\n"
|
||||
" fft_cc <fft_size> <out_of_every_n_samples> [window [--octave] [--benchmark]]\n"
|
||||
" logpower_cf [add_db]\n"
|
||||
|
@ -1343,14 +1344,57 @@ int main(int argc, char *argv[])
|
|||
firdes_lowpass_f(taps, taps_length, 0.59*0.5/(rate-transition_bw), window); //0.6 const to compensate rolloff
|
||||
//for(int=0;i<taps_length; i++) fprintf(stderr,"%g ",taps[i]);
|
||||
|
||||
static fractional_decimator_ff_t d; //in .bss => initialized to zero
|
||||
fprintf(stderr,"fractional_decimator_ff: not using taps\n");
|
||||
fractional_decimator_ff_t d = fractional_decimator_ff_init(rate, 4, NULL, 0);
|
||||
for(;;)
|
||||
{
|
||||
FEOF_CHECK;
|
||||
if(d.input_processed==0) d.input_processed=the_bufsize;
|
||||
else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed));
|
||||
fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin);
|
||||
d = fractional_decimator_ff(input_buffer, output_buffer, the_bufsize, rate, taps, taps_length, d);
|
||||
fractional_decimator_ff(input_buffer, output_buffer, the_bufsize, &d);
|
||||
fwrite(output_buffer, sizeof(float), d.output_size, stdout);
|
||||
TRY_YIELD;
|
||||
}
|
||||
}
|
||||
|
||||
if(!strcmp(argv[1],"old_fractional_decimator_ff"))
|
||||
{
|
||||
//Process the params
|
||||
if(argc<=2) return badsyntax("need required parameters (rate)");
|
||||
float rate;
|
||||
sscanf(argv[2],"%g",&rate);
|
||||
|
||||
float transition_bw=0.03;
|
||||
if(argc>=4) sscanf(argv[3],"%g",&transition_bw);
|
||||
|
||||
window_t window = WINDOW_DEFAULT;
|
||||
if(argc>=5)
|
||||
{
|
||||
window = firdes_get_window_from_string(argv[4]);
|
||||
}
|
||||
else fprintf(stderr,"old_fractional_decimator_ff: window = %s\n",firdes_get_string_from_window(window));
|
||||
|
||||
if(!initialize_buffers()) return -2;
|
||||
sendbufsize(the_bufsize / rate);
|
||||
|
||||
if(rate==1) clone_(the_bufsize); //copy input to output in this special case (and stick in this function).
|
||||
|
||||
//Generate filter taps
|
||||
int taps_length = firdes_filter_len(transition_bw);
|
||||
fprintf(stderr,"old_fractional_decimator_ff: taps_length = %d\n",taps_length);
|
||||
float* taps = (float*)malloc(sizeof(float)*taps_length);
|
||||
firdes_lowpass_f(taps, taps_length, 0.59*0.5/(rate-transition_bw), window); //0.6 const to compensate rolloff
|
||||
//for(int=0;i<taps_length; i++) fprintf(stderr,"%g ",taps[i]);
|
||||
|
||||
static old_fractional_decimator_ff_t d; //in .bss => initialized to zero
|
||||
for(;;)
|
||||
{
|
||||
FEOF_CHECK;
|
||||
if(d.input_processed==0) d.input_processed=the_bufsize;
|
||||
else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed));
|
||||
fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin);
|
||||
d = old_fractional_decimator_ff(input_buffer, output_buffer, the_bufsize, rate, taps, taps_length, d);
|
||||
fwrite(output_buffer, sizeof(float), d.output_size, stdout);
|
||||
TRY_YIELD;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
94
libcsdr.c
94
libcsdr.c
|
@ -654,7 +654,7 @@ float inline fir_one_pass_ff(float* input, float* taps, int taps_length)
|
|||
return acc;
|
||||
}
|
||||
|
||||
fractional_decimator_ff_t fractional_decimator_ff(float* input, float* output, int input_size, float rate, float *taps, int taps_length, fractional_decimator_ff_t d)
|
||||
old_fractional_decimator_ff_t old_fractional_decimator_ff(float* input, float* output, int input_size, float rate, float *taps, int taps_length, old_fractional_decimator_ff_t d)
|
||||
{
|
||||
if(rate<=1.0) return d; //sanity check, can't decimate <=1.0
|
||||
//This routine can handle floating point decimation rates.
|
||||
|
@ -687,6 +687,98 @@ fractional_decimator_ff_t fractional_decimator_ff(float* input, float* output, i
|
|||
return d;
|
||||
}
|
||||
|
||||
fractional_decimator_ff_t fractional_decimator_ff_init(float rate, int num_poly_points, float* taps, int taps_length)
|
||||
{
|
||||
fractional_decimator_ff_t d;
|
||||
d.num_poly_points = num_poly_points&~1; //num_poly_points needs to be even!
|
||||
d.poly_precalc_denomiator = (float*)malloc(d.num_poly_points*sizeof(float));
|
||||
//x0..x3
|
||||
//-1,0,1,2
|
||||
//-(4/2)+1
|
||||
//x0..x5
|
||||
//-2,-1,0,1,2,3
|
||||
d.xifirst=-(num_poly_points/2)+1, d.xilast=num_poly_points/2;
|
||||
int id = 0; //index in poly_precalc_denomiator
|
||||
for(int xi=d.xifirst;xi<=d.xilast;xi++)
|
||||
{
|
||||
d.poly_precalc_denomiator[id]=1;
|
||||
for(int xj=d.xifirst;xj<=d.xilast;xj++)
|
||||
{
|
||||
if(xi!=xj) d.poly_precalc_denomiator[id] *= (xi-xj); //poly_precalc_denomiator could be integer as well. But that would later add a necessary conversion.
|
||||
}
|
||||
id++;
|
||||
}
|
||||
d.where=-d.xifirst;
|
||||
d.coeffs_buf=(float*)malloc(d.num_poly_points*sizeof(float));
|
||||
d.filtered_buf=(float*)malloc(d.num_poly_points*sizeof(float));
|
||||
//d.last_inputs_circbuf = (float)malloc(d.num_poly_points*sizeof(float));
|
||||
//d.last_inputs_startsat = 0;
|
||||
//d.last_inputs_samplewhere = -1;
|
||||
//for(int i=0;i<num_poly_points; i++) d.last_inputs_circbuf[i] = 0;
|
||||
d.rate = rate;
|
||||
d.taps = taps;
|
||||
d.taps_length = taps_length;
|
||||
return d;
|
||||
}
|
||||
|
||||
#define DEBUG_ASSERT 1
|
||||
void fractional_decimator_ff(float* input, float* output, int input_size, fractional_decimator_ff_t* d)
|
||||
{
|
||||
//This routine can handle floating point decimation rates.
|
||||
//It applies polynomial interpolation to samples that are taken into consideration from a pre-filtered input.
|
||||
//The pre-filter can be switched off by applying taps=NULL.
|
||||
//fprintf(stderr, "drate=%f\n", d->rate);
|
||||
if(DEBUG_ASSERT) assert(d->rate > 1.0);
|
||||
int oi=0; //output index
|
||||
int index_high;
|
||||
#define FD_INDEX_LOW (index_high-1)
|
||||
//we optimize to calculate ceilf(where) only once every iteration, so we do it here:
|
||||
for(;(index_high=ceilf(d->where))+d->taps_length<input_size;d->where+=d->rate) //@fractional_decimator_ff
|
||||
{
|
||||
int sxifirst = FD_INDEX_LOW + d->xifirst;
|
||||
int sxilast = FD_INDEX_LOW + d->xilast;
|
||||
if(d->taps) for(int wi=0;wi<d->num_poly_points;wi++) d->filtered_buf[wi] = fir_one_pass_ff(input+FD_INDEX_LOW+wi, d->taps, d->taps_length);
|
||||
else for(int wi=0;wi<d->num_poly_points;wi++) d->filtered_buf[wi] = *(input+FD_INDEX_LOW+wi);
|
||||
int id=0;
|
||||
float xwhere = d->where - FD_INDEX_LOW;
|
||||
for(int xi=d->xifirst;xi<=d->xilast;xi++)
|
||||
{
|
||||
d->coeffs_buf[id]=1;
|
||||
for(int xj=d->xifirst;xj<=d->xilast;xj++)
|
||||
{
|
||||
if(xi!=xj) d->coeffs_buf[id] *= (xwhere-xj);
|
||||
}
|
||||
id++;
|
||||
}
|
||||
float acc = 0;
|
||||
for(int i=0;i<d->num_poly_points;i++)
|
||||
{
|
||||
acc += (d->coeffs_buf[i]/d->poly_precalc_denomiator[i])*d->filtered_buf[i]; //(xnom/xden)*yn
|
||||
}
|
||||
output[oi++]=acc;
|
||||
}
|
||||
d->input_processed=FD_INDEX_LOW + d->xifirst;
|
||||
d->where-=d->input_processed;
|
||||
if(DEBUG_ASSERT) assert(d->where >= -d->xifirst);
|
||||
d->output_size=oi;
|
||||
}
|
||||
|
||||
/*
|
||||
int last_input_samplewhere_shouldbe = (index_high-1)+xifirst;
|
||||
int last_input_offset = last_input_samplewhere_shouldbe - d->last_input_samplewhere;
|
||||
if(last_input_offset < num_poly_points)
|
||||
{
|
||||
//if we can move the last_input circular buffer, we move, and add the new samples at the end
|
||||
d->last_inputs_startsat += last_input_offset;
|
||||
d->last_inputs_startsat %= num_poly_points;
|
||||
int num_copied_samples = 0;
|
||||
for(int i=0; i<last_input_offset; i++)
|
||||
{
|
||||
d->last_inputs_circbuf[i]=
|
||||
}
|
||||
d->last_input_samplewhere = d->las
|
||||
}
|
||||
*/
|
||||
|
||||
void apply_fir_fft_cc(FFT_PLAN_T* plan, FFT_PLAN_T* plan_inverse, complexf* taps_fft, complexf* last_overlap, int overlap_size)
|
||||
{
|
||||
|
|
25
libcsdr.h
25
libcsdr.h
|
@ -146,12 +146,33 @@ void accumulate_power_cf(complexf* input, float* output, int size);
|
|||
void log_ff(float* input, float* output, int size, float add_db);
|
||||
|
||||
typedef struct fractional_decimator_ff_s
|
||||
{
|
||||
float where;
|
||||
int input_processed;
|
||||
int output_size;
|
||||
int num_poly_points; //number of samples that the Lagrange interpolator will use
|
||||
float* poly_precalc_denomiator; //while we don't precalculate coefficients here as in a Farrow structure, because it is a fractional interpolator, but we rather precaculate part of the interpolator expression
|
||||
//float* last_inputs_circbuf; //circular buffer to store the last (num_poly_points) number of input samples.
|
||||
//int last_inputs_startsat; //where the circular buffer starts now
|
||||
//int last_inputs_samplewhere;
|
||||
float* coeffs_buf;
|
||||
float* filtered_buf;
|
||||
int xifirst;
|
||||
int xilast;
|
||||
float rate;
|
||||
float *taps;
|
||||
int taps_length;
|
||||
} fractional_decimator_ff_t;
|
||||
fractional_decimator_ff_t fractional_decimator_ff_init(float rate, int num_poly_points, float* taps, int taps_length);
|
||||
void fractional_decimator_ff(float* input, float* output, int input_size, fractional_decimator_ff_t* d);
|
||||
|
||||
typedef struct old_fractional_decimator_ff_s
|
||||
{
|
||||
float remain;
|
||||
int input_processed;
|
||||
int output_size;
|
||||
} fractional_decimator_ff_t;
|
||||
fractional_decimator_ff_t fractional_decimator_ff(float* input, float* output, int input_size, float rate, float *taps, int taps_length, fractional_decimator_ff_t d);
|
||||
} old_fractional_decimator_ff_t;
|
||||
old_fractional_decimator_ff_t old_fractional_decimator_ff(float* input, float* output, int input_size, float rate, float *taps, int taps_length, old_fractional_decimator_ff_t d);
|
||||
|
||||
typedef struct shift_table_data_s
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue