Fixed a lot of things related to fractional decimator

This commit is contained in:
ha7ilm 2017-02-28 00:27:41 +01:00
parent 875434bf96
commit c7d9aa05e7
4 changed files with 352 additions and 29 deletions

View file

@ -312,11 +312,16 @@ The output sample rate will be `interpolation / decimation × input_sample_rate`
`transition_bw` and `window` are the parameters of the filter. `transition_bw` and `window` are the parameters of the filter.
fractional_decimator_ff <decimation_rate> [transition_bw [window]] fractional_decimator_ff <decimation_rate> [num_poly_points ( [transition_bw [window]] | --prefilter )]
It can decimate by a floating point ratio. It can decimate by a floating point ratio.
`transition_bw` and `window` are the parameters of the filter. It uses Lagrance interpolation, where `num_poly_points` (12 by default) input samples are taken into consideration while calculating one output sample.
It can use an additional FIR filter before applying the Lagrange interpolation. This filter can be activated by:
* passing only the `transition_bw`, or both the `transition_bw` and the `window` parameters of the filter,
* using the `--prefilter` switch after `num_poly_points` to switch this filter on with the default parameters.
bandpass_fir_fft_cc <low_cut> <high_cut> <transition_bw> [window] bandpass_fir_fft_cc <low_cut> <high_cut> <transition_bw> [window]

44
csdr.c
View file

@ -98,7 +98,7 @@ char usage[]=
" 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" " old_fractional_decimator_ff <decimation_rate> [transition_bw [window]]\n"
" fractional_decimator_ff <decimation_rate> [transition_bw [window]]\n" " fractional_decimator_ff <decimation_rate> [num_poly_points ( [transition_bw [window]] | --prefilter )]\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"
" fft_benchmark <fft_size> <fft_cycles> [--benchmark]\n" " fft_benchmark <fft_size> <fft_cycles> [--benchmark]\n"
@ -1322,15 +1322,29 @@ int main(int argc, char *argv[])
float rate; float rate;
sscanf(argv[2],"%g",&rate); sscanf(argv[2],"%g",&rate);
float transition_bw=0.03; int num_poly_points = 12;
if(argc>=4) sscanf(argv[3],"%g",&transition_bw); if(argc>=4) sscanf(argv[3],"%d",&num_poly_points);
if(num_poly_points&1) return badsyntax("num_poly_points should be even");
if(num_poly_points<2) return badsyntax("num_poly_points should be >= 2");
int use_prefilter = 0;
float transition_bw=0.03;
window_t window = WINDOW_DEFAULT; window_t window = WINDOW_DEFAULT;
if(argc>=5) if(argc>=5)
{ {
window = firdes_get_window_from_string(argv[4]); if(!strcmp(argv[4], "--prefilter"))
{
fprintf(stderr, "fractional_decimator_ff: using prefilter with default values\n");
use_prefilter = 1;
}
else
{
sscanf(argv[4],"%g",&transition_bw);
if(argc>=6) window = firdes_get_window_from_string(argv[5]);
}
} }
else fprintf(stderr,"fractional_decimator_ff: window = %s\n",firdes_get_string_from_window(window)); fprintf(stderr,"fractional_decimator_ff: use_prefilter = %d, num_poly_points = %d, transition_bw = %g, window = %s\n",
use_prefilter, num_poly_points, transition_bw, firdes_get_string_from_window(window));
if(!initialize_buffers()) return -2; if(!initialize_buffers()) return -2;
sendbufsize(the_bufsize / rate); sendbufsize(the_bufsize / rate);
@ -1338,14 +1352,18 @@ int main(int argc, char *argv[])
if(rate==1) clone_(the_bufsize); //copy input to output in this special case (and stick in this function). if(rate==1) clone_(the_bufsize); //copy input to output in this special case (and stick in this function).
//Generate filter taps //Generate filter taps
int taps_length = firdes_filter_len(transition_bw); int taps_length = 0;
fprintf(stderr,"fractional_decimator_ff: taps_length = %d\n",taps_length); float* taps = NULL;
float* taps = (float*)malloc(sizeof(float)*taps_length); if(use_prefilter)
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]); taps_length = firdes_filter_len(transition_bw);
fprintf(stderr,"fractional_decimator_ff: taps_length = %d\n",taps_length);
fprintf(stderr,"fractional_decimator_ff: not using taps\n"); taps = (float*)malloc(sizeof(float)*taps_length);
fractional_decimator_ff_t d = fractional_decimator_ff_init(rate, 16, NULL, 0); firdes_lowpass_f(taps, taps_length, 0.5/(rate-transition_bw), window); //0.6 const to compensate rolloff
//for(int=0;i<taps_length; i++) fprintf(stderr,"%g ",taps[i]);
}
else fprintf(stderr,"fractional_decimator_ff: not using taps\n");
fractional_decimator_ff_t d = fractional_decimator_ff_init(rate, num_poly_points, taps, taps_length);
for(;;) for(;;)
{ {
FEOF_CHECK; FEOF_CHECK;

View file

@ -124,7 +124,7 @@
</param> </param>
<param> <param>
<key>grid_pos</key> <key>grid_pos</key>
<value>2, 1, 1, 1</value> <value>1, 1, 1, 1</value>
</param> </param>
<param> <param>
<key>id</key> <key>id</key>
@ -292,7 +292,7 @@
</param> </param>
<param> <param>
<key>_coordinate</key> <key>_coordinate</key>
<value>(168, 115)</value> <value>(168, 163)</value>
</param> </param>
<param> <param>
<key>_rotation</key> <key>_rotation</key>
@ -316,7 +316,7 @@
</param> </param>
<param> <param>
<key>samples_per_second</key> <key>samples_per_second</key>
<value>samp_rate</value> <value>samp_rate/5</value>
</param> </param>
<param> <param>
<key>type</key> <key>type</key>
@ -386,7 +386,7 @@
</param> </param>
<param> <param>
<key>commandline</key> <key>commandline</key>
<value>"csdr fractional_decimator_ff "+str(decimation)</value> <value>"csdr fractional_decimator_ff "+str(decimation)+" 20"</value>
</param> </param>
<param> <param>
<key>comment</key> <key>comment</key>
@ -402,7 +402,7 @@
</param> </param>
<param> <param>
<key>_coordinate</key> <key>_coordinate</key>
<value>(352, 115)</value> <value>(368, 91)</value>
</param> </param>
<param> <param>
<key>_rotation</key> <key>_rotation</key>
@ -425,6 +425,53 @@
<value>ff</value> <value>ff</value>
</param> </param>
</block> </block>
<block>
<key>ha5kfu_execproc_xx</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>commandline</key>
<value>"csdr old_fractional_decimator_ff "+str(decimation)</value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(840, 379)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>ha5kfu_execproc_xx_0_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>type</key>
<value>ff</value>
</param>
</block>
<block> <block>
<key>notebook</key> <key>notebook</key>
<param> <param>
@ -449,7 +496,7 @@
</param> </param>
<param> <param>
<key>grid_pos</key> <key>grid_pos</key>
<value>1,2,1,1</value> <value>2,2,1,1</value>
</param> </param>
<param> <param>
<key>id</key> <key>id</key>
@ -492,7 +539,7 @@
</param> </param>
<param> <param>
<key>grid_pos</key> <key>grid_pos</key>
<value>1,1,1,1</value> <value>2,1,1,1</value>
</param> </param>
<param> <param>
<key>id</key> <key>id</key>
@ -535,7 +582,7 @@
</param> </param>
<param> <param>
<key>grid_pos</key> <key>grid_pos</key>
<value>2,2,1,1</value> <value>3,2,1,1</value>
</param> </param>
<param> <param>
<key>id</key> <key>id</key>
@ -554,6 +601,49 @@
<value>wx.NB_TOP</value> <value>wx.NB_TOP</value>
</param> </param>
</block> </block>
<block>
<key>notebook</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(16, 795)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>grid_pos</key>
<value>3,1,1,1</value>
</param>
<param>
<key>id</key>
<value>nb3</value>
</param>
<param>
<key>labels</key>
<value>['scope','fft']</value>
</param>
<param>
<key>notebook</key>
<value></value>
</param>
<param>
<key>style</key>
<value>wx.NB_TOP</value>
</param>
</block>
<block> <block>
<key>wxgui_fftsink2</key> <key>wxgui_fftsink2</key>
<param> <param>
@ -594,7 +684,7 @@
</param> </param>
<param> <param>
<key>_coordinate</key> <key>_coordinate</key>
<value>(640, 235)</value> <value>(736, 147)</value>
</param> </param>
<param> <param>
<key>_rotation</key> <key>_rotation</key>
@ -634,7 +724,7 @@
</param> </param>
<param> <param>
<key>title</key> <key>title</key>
<value>Resampled signal (csdr)</value> <value>Resampled signal (csdr, new)</value>
</param> </param>
<param> <param>
<key>type</key> <key>type</key>
@ -760,6 +850,109 @@
<value>10</value> <value>10</value>
</param> </param>
</block> </block>
<block>
<key>wxgui_fftsink2</key>
<param>
<key>avg_alpha</key>
<value>0</value>
</param>
<param>
<key>average</key>
<value>False</value>
</param>
<param>
<key>baseband_freq</key>
<value>0</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>fft_size</key>
<value>1024</value>
</param>
<param>
<key>freqvar</key>
<value>None</value>
</param>
<param>
<key>_coordinate</key>
<value>(1112, 139)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>grid_pos</key>
<value></value>
</param>
<param>
<key>id</key>
<value>wxgui_fftsink2_0_1</value>
</param>
<param>
<key>notebook</key>
<value>nb3,1</value>
</param>
<param>
<key>peak_hold</key>
<value>False</value>
</param>
<param>
<key>ref_level</key>
<value>0</value>
</param>
<param>
<key>ref_scale</key>
<value>2.0</value>
</param>
<param>
<key>fft_rate</key>
<value>15</value>
</param>
<param>
<key>samp_rate</key>
<value>samp_rate_2</value>
</param>
<param>
<key>title</key>
<value>Resampled signal (csdr, old)</value>
</param>
<param>
<key>type</key>
<value>float</value>
</param>
<param>
<key>win_size</key>
<value></value>
</param>
<param>
<key>win</key>
<value>None</value>
</param>
<param>
<key>y_divs</key>
<value>16</value>
</param>
<param>
<key>y_per_div</key>
<value>10</value>
</param>
</block>
<block> <block>
<key>wxgui_fftsink2</key> <key>wxgui_fftsink2</key>
<param> <param>
@ -887,7 +1080,7 @@
</param> </param>
<param> <param>
<key>_coordinate</key> <key>_coordinate</key>
<value>(640, 115)</value> <value>(728, 27)</value>
</param> </param>
<param> <param>
<key>_rotation</key> <key>_rotation</key>
@ -919,7 +1112,7 @@
</param> </param>
<param> <param>
<key>title</key> <key>title</key>
<value>Resampled signal (csdr)</value> <value>Resampled signal (csdr, new)</value>
</param> </param>
<param> <param>
<key>trig_mode</key> <key>trig_mode</key>
@ -1124,6 +1317,93 @@
<value>Counts</value> <value>Counts</value>
</param> </param>
</block> </block>
<block>
<key>wxgui_scopesink2</key>
<param>
<key>ac_couple</key>
<value>False</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(1112, 19)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>grid_pos</key>
<value></value>
</param>
<param>
<key>id</key>
<value>wxgui_scopesink2_0_2</value>
</param>
<param>
<key>notebook</key>
<value>nb3,0</value>
</param>
<param>
<key>num_inputs</key>
<value>1</value>
</param>
<param>
<key>samp_rate</key>
<value>samp_rate_2</value>
</param>
<param>
<key>t_scale</key>
<value>0</value>
</param>
<param>
<key>title</key>
<value>Resampled signal (csdr, old)</value>
</param>
<param>
<key>trig_mode</key>
<value>wxgui.TRIG_MODE_AUTO</value>
</param>
<param>
<key>type</key>
<value>float</value>
</param>
<param>
<key>v_offset</key>
<value>0</value>
</param>
<param>
<key>v_scale</key>
<value>0</value>
</param>
<param>
<key>win_size</key>
<value></value>
</param>
<param>
<key>xy_mode</key>
<value>False</value>
</param>
<param>
<key>y_axis_label</key>
<value>Counts</value>
</param>
</block>
<connection> <connection>
<source_block_id>analog_sig_source_x_0</source_block_id> <source_block_id>analog_sig_source_x_0</source_block_id>
<sink_block_id>blocks_throttle_0</sink_block_id> <sink_block_id>blocks_throttle_0</sink_block_id>
@ -1142,6 +1422,12 @@
<source_key>0</source_key> <source_key>0</source_key>
<sink_key>0</sink_key> <sink_key>0</sink_key>
</connection> </connection>
<connection>
<source_block_id>blocks_throttle_0</source_block_id>
<sink_block_id>ha5kfu_execproc_xx_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection> <connection>
<source_block_id>blocks_throttle_0</source_block_id> <source_block_id>blocks_throttle_0</source_block_id>
<sink_block_id>wxgui_fftsink2_1</sink_block_id> <sink_block_id>wxgui_fftsink2_1</sink_block_id>
@ -1178,4 +1464,16 @@
<source_key>0</source_key> <source_key>0</source_key>
<sink_key>0</sink_key> <sink_key>0</sink_key>
</connection> </connection>
<connection>
<source_block_id>ha5kfu_execproc_xx_0_0</source_block_id>
<sink_block_id>wxgui_fftsink2_0_1</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>ha5kfu_execproc_xx_0_0</source_block_id>
<sink_block_id>wxgui_scopesink2_0_2</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
</flow_graph> </flow_graph>

View file

@ -739,8 +739,10 @@ void fractional_decimator_ff(float* input, float* output, int input_size, fracti
//d->num_poly_points above is theoretically more than we could have here, but this makes the spectrum look good //d->num_poly_points above is theoretically more than we could have here, but this makes the spectrum look good
int sxifirst = FD_INDEX_LOW + d->xifirst; int sxifirst = FD_INDEX_LOW + d->xifirst;
int sxilast = FD_INDEX_LOW + d->xilast; 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); if(d->taps)
else for(int wi=0;wi<d->num_poly_points;wi++) d->filtered_buf[wi] = *(input+FD_INDEX_LOW+wi); 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; int id=0;
float xwhere = d->where - FD_INDEX_LOW; float xwhere = d->where - FD_INDEX_LOW;
for(int xi=d->xifirst;xi<=d->xilast;xi++) for(int xi=d->xifirst;xi<=d->xilast;xi++)