Merged fir_interpolate_cc
This commit is contained in:
commit
f88766677a
5 changed files with 1309 additions and 1 deletions
|
@ -315,7 +315,12 @@ Other parameters were explained above at `firdes_lowpass_f`.
|
|||
fir_decimate_cc <decimation_factor> [transition_bw [window]]
|
||||
|
||||
It is a decimator that keeps one sample out of `decimation_factor` samples.
|
||||
To avoid aliasing, it runs a filter on the signal and removes spectral components above `0.5 × nyquist_frequency × decimation_factor`.
|
||||
To avoid aliasing, it runs a filter on the signal and removes spectral components above `0.5 × nyquist_frequency × decimation_factor` from the input signal.
|
||||
|
||||
fir_interpolate_cc <interpolation_factor> [transition_bw [window]]
|
||||
|
||||
It is an interpolator that generates `interpolation_factor` number of output samples from one input sample.
|
||||
To avoid aliasing, it runs a filter on the signal and removes spectral components above `0.5 × nyquist_frequency / interpolation_factor` from the output signal.
|
||||
|
||||
`transition_bw` and `window` are the parameters of the filter.
|
||||
|
||||
|
|
62
csdr.c
62
csdr.c
|
@ -51,6 +51,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
#include "fastddc.h"
|
||||
#include <assert.h>
|
||||
|
||||
char usage[]=
|
||||
"csdr - a simple commandline tool for Software Defined Radio receiver DSP.\n\n"
|
||||
|
@ -92,6 +93,7 @@ char usage[]=
|
|||
" amdemod_cf\n"
|
||||
" amdemod_estimator_cf\n"
|
||||
" fir_decimate_cc <decimation_factor> [transition_bw [window]]\n"
|
||||
" fir_interpolate_cc <interpolation_factor> [transition_bw [window]]\n"
|
||||
" firdes_lowpass_f <cutoff_rate> <length> [window [--octave]]\n"
|
||||
" firdes_bandpass_c <low_cut> <high_cut> <length> [window [--octave]]\n"
|
||||
" agc_ff [hang_time [reference [attack_rate [decay_rate [max_gain [attack_wait [filter_alpha]]]]]]]\n"
|
||||
|
@ -1104,6 +1106,66 @@ int main(int argc, char *argv[])
|
|||
//fprintf(stderr,"iskip=%d output_size=%d start=%x target=%x skipcount=%x \n",input_skip,output_size,input_buffer, ((complexf*)input_buffer)+(BIG_BUFSIZE-input_skip),(BIG_BUFSIZE-input_skip));
|
||||
}
|
||||
}
|
||||
|
||||
if(!strcmp(argv[1],"fir_interpolate_cc"))
|
||||
{
|
||||
bigbufs=1;
|
||||
|
||||
if(argc<=2) return badsyntax("need required parameter (interpolation factor)");
|
||||
|
||||
int factor;
|
||||
sscanf(argv[2],"%d",&factor);
|
||||
assert(factor >= 1);
|
||||
|
||||
float transition_bw = 0.05;
|
||||
if(argc>=4) sscanf(argv[3],"%g",&transition_bw);
|
||||
assert(transition_bw >= 0 && transition_bw < 1.);
|
||||
|
||||
window_t window = WINDOW_DEFAULT;
|
||||
if(argc>=5)
|
||||
{
|
||||
window=firdes_get_window_from_string(argv[4]);
|
||||
}
|
||||
else fprintf(stderr,"fir_interpolate_cc: window = %s\n",firdes_get_string_from_window(window));
|
||||
|
||||
int taps_length=firdes_filter_len(transition_bw);
|
||||
fprintf(stderr,"fir_interpolate_cc: taps_length = %d\n",taps_length);
|
||||
assert(taps_length > 0);
|
||||
|
||||
while (env_csdr_fixed_big_bufsize < taps_length*2) env_csdr_fixed_big_bufsize*=2; //temporary fix for buffer size if [transition_bw] is low
|
||||
//fprintf(stderr, "env_csdr_fixed_big_bufsize = %d\n", env_csdr_fixed_big_bufsize);
|
||||
|
||||
if(!initialize_buffers()) return -2;
|
||||
sendbufsize(the_bufsize*factor);
|
||||
assert(the_bufsize > 0);
|
||||
|
||||
float *taps;
|
||||
taps=(float*)malloc(taps_length*sizeof(float));
|
||||
assert(taps);
|
||||
|
||||
firdes_lowpass_f(taps,taps_length,0.5/(float)factor,window);
|
||||
|
||||
int input_skip=0;
|
||||
int output_size=0;
|
||||
float* interp_output_buffer = (float*)malloc(sizeof(float)*2*the_bufsize*factor);
|
||||
for(;;)
|
||||
{
|
||||
FEOF_CHECK;
|
||||
output_size=fir_interpolate_cc((complexf*)input_buffer, (complexf*)interp_output_buffer, the_bufsize, factor, taps, taps_length);
|
||||
//fprintf(stderr, "os %d\n",output_size);
|
||||
fwrite(interp_output_buffer, sizeof(complexf), output_size, stdout);
|
||||
fflush(stdout);
|
||||
TRY_YIELD;
|
||||
input_skip=output_size/factor;
|
||||
memmove((complexf*)input_buffer,((complexf*)input_buffer)+input_skip,(the_bufsize-input_skip)*sizeof(complexf)); //memmove lets the source and destination overlap
|
||||
fread(((complexf*)input_buffer)+(the_bufsize-input_skip), sizeof(complexf), input_skip, stdin);
|
||||
//fprintf(stderr,"iskip=%d output_size=%d start=%x target=%x skipcount=%x \n",input_skip,output_size,input_buffer, ((complexf*)input_buffer)+(BIG_BUFSIZE-input_skip),(BIG_BUFSIZE-input_skip));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*if(!strcmp(argv[1],"ejw_test"))
|
||||
{
|
||||
printf("ejqd=[");
|
||||
|
|
1212
grc_tests/test_fir_interpolate_cc.grc
Normal file
1212
grc_tests/test_fir_interpolate_cc.grc
Normal file
File diff suppressed because it is too large
Load diff
28
libcsdr.c
28
libcsdr.c
|
@ -580,6 +580,34 @@ int fir_decimate_cc(complexf *input, complexf *output, int input_size, int decim
|
|||
}
|
||||
*/
|
||||
|
||||
int fir_interpolate_cc(complexf *input, complexf *output, int input_size, int interpolation, float *taps, int taps_length)
|
||||
{
|
||||
//i: input index
|
||||
//oi: output index
|
||||
//ti: tap index
|
||||
//ti: secondary index (inside filter function)
|
||||
//ip: interpolation phase (0 <= ip < interpolation)
|
||||
int oi=0;
|
||||
for(int i=0; i<input_size; i++) //@fir_interpolate_cc: outer loop
|
||||
{
|
||||
if(i*interpolation + (interpolation-1) + taps_length > input_size*interpolation) break;
|
||||
for(int ip=0; ip<interpolation; ip++)
|
||||
{
|
||||
float acci=0;
|
||||
float accq=0;
|
||||
//int tistart = (interpolation-ip)%interpolation;
|
||||
int tistart = (interpolation-ip); //why does this work? why don't we need the % part?
|
||||
for(int ti=tistart, si=0; ti<taps_length; (ti+=interpolation), (si++)) acci += (iof(input,i+si)) * taps[ti]; //@fir_interpolate_cc: i loop
|
||||
for(int ti=tistart, si=0; ti<taps_length; (ti+=interpolation), (si++)) accq += (qof(input,i+si)) * taps[ti]; //@fir_interpolate_cc: q loop
|
||||
iof(output,oi)=acci;
|
||||
qof(output,oi)=accq;
|
||||
oi++;
|
||||
}
|
||||
}
|
||||
return oi;
|
||||
}
|
||||
|
||||
|
||||
rational_resampler_ff_t rational_resampler_ff(float *input, float *output, int input_size, int interpolation, int decimation, float *taps, int taps_length, int last_taps_delay)
|
||||
{
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ void limit_ff(float* input, float* output, int input_size, float max_amplitude);
|
|||
//filters, decimators, resamplers, shift, etc.
|
||||
float fir_one_pass_ff(float* input, float* taps, int taps_length);
|
||||
int fir_decimate_cc(complexf *input, complexf *output, int input_size, int decimation, float *taps, int taps_length);
|
||||
int fir_interpolate_cc(complexf *input, complexf *output, int input_size, int interpolation, float *taps, int taps_length);
|
||||
int deemphasis_nfm_ff (float* input, float* output, int input_size, int sample_rate);
|
||||
float deemphasis_wfm_ff (float* input, float* output, int input_size, float tau, int sample_rate, float last_output);
|
||||
float shift_math_cc(complexf *input, complexf* output, int input_size, float rate, float starting_phase);
|
||||
|
|
Loading…
Reference in a new issue