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
|
*.so
|
||||||
tags
|
tags
|
||||||
dumpvect.*.vect
|
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"
|
" agc_ff [hang_time [reference [attack_rate [decay_rate [max_gain [attack_wait [filter_alpha]]]]]]]\n"
|
||||||
" fastagc_ff [block_size [reference]]\n"
|
" fastagc_ff [block_size [reference]]\n"
|
||||||
" rational_resampler_ff <interpolation> <decimation> [transition_bw [window]]\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"
|
" fractional_decimator_ff <decimation_rate> [transition_bw [window]]\n"
|
||||||
" fft_cc <fft_size> <out_of_every_n_samples> [window [--octave] [--benchmark]]\n"
|
" fft_cc <fft_size> <out_of_every_n_samples> [window [--octave] [--benchmark]]\n"
|
||||||
" logpower_cf [add_db]\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
|
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]);
|
//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(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
FEOF_CHECK;
|
FEOF_CHECK;
|
||||||
if(d.input_processed==0) d.input_processed=the_bufsize;
|
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));
|
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);
|
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);
|
fwrite(output_buffer, sizeof(float), d.output_size, stdout);
|
||||||
TRY_YIELD;
|
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;
|
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
|
if(rate<=1.0) return d; //sanity check, can't decimate <=1.0
|
||||||
//This routine can handle floating point decimation rates.
|
//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;
|
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)
|
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);
|
void log_ff(float* input, float* output, int size, float add_db);
|
||||||
|
|
||||||
typedef struct fractional_decimator_ff_s
|
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;
|
float remain;
|
||||||
int input_processed;
|
int input_processed;
|
||||||
int output_size;
|
int output_size;
|
||||||
} fractional_decimator_ff_t;
|
} old_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(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
|
typedef struct shift_table_data_s
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue