Skip to content

Commit 574dd91

Browse files
committed
Merged teejez -> feature/digitalmods
2 parents ac8e1b6 + 03724f3 commit 574dd91

6 files changed

Lines changed: 172 additions & 0 deletions

File tree

csdr.c

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3170,6 +3170,141 @@ int main(int argc, char *argv[])
31703170
return 0;
31713171
}
31723172

3173+
if(!strcmp(argv[1],"shift_addition_fc"))
3174+
{
3175+
bigbufs=1;
3176+
3177+
float starting_phase=0;
3178+
float rate;
3179+
3180+
int fd;
3181+
if(fd=init_fifo(argc,argv))
3182+
{
3183+
while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000);
3184+
}
3185+
else
3186+
{
3187+
if(argc<=2) return badsyntax("need required parameter (rate)");
3188+
sscanf(argv[2],"%g",&rate);
3189+
}
3190+
3191+
if(!sendbufsize(initialize_buffers())) return -2;
3192+
for(;;)
3193+
{
3194+
shift_addition_data_t data=shift_addition_init(rate);
3195+
fprintf(stderr,"shift_addition_fc: reinitialized to %g\n",rate);
3196+
int remain, current_size;
3197+
float* ibufptr;
3198+
float* obufptr;
3199+
for(;;)
3200+
{
3201+
FEOF_CHECK;
3202+
if(!FREAD_R) break;
3203+
remain=the_bufsize;
3204+
ibufptr=input_buffer;
3205+
obufptr=output_buffer;
3206+
while(remain)
3207+
{
3208+
current_size=(remain>1024)?1024:remain;
3209+
starting_phase=shift_addition_fc(ibufptr, (complexf*)obufptr, current_size, data, starting_phase);
3210+
ibufptr+=current_size;
3211+
obufptr+=current_size*2;
3212+
remain-=current_size;
3213+
}
3214+
FWRITE_C;
3215+
if(read_fifo_ctl(fd,"%g\n",&rate)) break;
3216+
TRY_YIELD;
3217+
}
3218+
}
3219+
return 0;
3220+
}
3221+
3222+
if(!strcmp(argv[1],"fft_fc"))
3223+
{
3224+
/*
3225+
For real FFT, the parameter is the number of output complex bins
3226+
instead of the actual FFT size.
3227+
Number of input samples used for each FFT is twice the given parameter.
3228+
This makes it easier to replace fft_cc by fft_fc in some applications. */
3229+
if(argc<=3) return badsyntax("need required parameters (fft_out_size, out_of_every_n_samples)");
3230+
int fft_in_size=0, fft_out_size=0;
3231+
sscanf(argv[2],"%d",&fft_out_size);
3232+
if(log2n(fft_out_size)==-1) return badsyntax("fft_out_size should be power of 2");
3233+
fft_in_size = 2*fft_out_size;
3234+
int every_n_samples;
3235+
sscanf(argv[3],"%d",&every_n_samples);
3236+
int benchmark=0;
3237+
int octave=0;
3238+
window_t window = WINDOW_DEFAULT;
3239+
if(argc>=5)
3240+
{
3241+
window=firdes_get_window_from_string(argv[4]);
3242+
}
3243+
if(argc>=6)
3244+
{
3245+
benchmark|=!strcmp("--benchmark",argv[5]);
3246+
octave|=!strcmp("--octave",argv[5]);
3247+
}
3248+
if(argc>=7)
3249+
{
3250+
benchmark|=!strcmp("--benchmark",argv[6]);
3251+
octave|=!strcmp("--octave",argv[6]);
3252+
}
3253+
3254+
if(!initialize_buffers()) return -2;
3255+
sendbufsize(fft_out_size);
3256+
3257+
//make FFT plan
3258+
float* input=(float*)fft_malloc(sizeof(float)*fft_in_size);
3259+
float* windowed=(float*)fft_malloc(sizeof(float)*fft_in_size);
3260+
complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_out_size);
3261+
if(benchmark) fprintf(stderr,"fft_cc: benchmarking...");
3262+
FFT_PLAN_T* plan=make_fft_r2c(fft_in_size, windowed, output, benchmark);
3263+
if(benchmark) fprintf(stderr," done\n");
3264+
//if(octave) printf("setenv(\"GNUTERM\",\"X11 noraise\");y=zeros(1,%d);semilogy(y,\"ydatasource\",\"y\");\n",fft_size); // TODO
3265+
float *windowt;
3266+
windowt = precalculate_window(fft_in_size, window);
3267+
for(;;)
3268+
{
3269+
FEOF_CHECK;
3270+
if(every_n_samples>fft_in_size)
3271+
{
3272+
fread(input, sizeof(float), fft_in_size, stdin);
3273+
//skipping samples before next FFT (but fseek doesn't work for pipes)
3274+
for(int seek_remain=every_n_samples-fft_in_size;seek_remain>0;seek_remain-=the_bufsize)
3275+
{
3276+
fread(temp_f, sizeof(complexf), MIN_M(the_bufsize,seek_remain), stdin);
3277+
}
3278+
}
3279+
else
3280+
{
3281+
//overlapped FFT
3282+
for(int i=0;i<fft_in_size-every_n_samples;i++) input[i]=input[i+every_n_samples];
3283+
fread(input+fft_in_size-every_n_samples, sizeof(float), every_n_samples, stdin);
3284+
}
3285+
//apply_window_c(input,windowed,fft_size,window);
3286+
apply_precalculated_window_f(input,windowed,fft_in_size,windowt);
3287+
fft_execute(plan);
3288+
if(octave)
3289+
{
3290+
#if 0
3291+
// TODO
3292+
printf("fftdata=[");
3293+
//we have to swap the two parts of the array to get a valid spectrum
3294+
for(int i=fft_size/2;i<fft_size;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i));
3295+
for(int i=0;i<fft_size/2;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i));
3296+
printf(
3297+
"];\n"
3298+
"y=abs(fftdata);\n"
3299+
"refreshdata;\n"
3300+
);
3301+
#endif
3302+
}
3303+
else fwrite(output, sizeof(complexf), fft_out_size, stdout);
3304+
TRY_YIELD;
3305+
}
3306+
}
3307+
31733308
if(!strcmp(argv[1],"none"))
31743309
{
31753310
return 0;

fft_fftw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct fft_plan_s
2222
#include "libcsdr.h"
2323

2424
FFT_PLAN_T* make_fft_c2c(int size, complexf* input, complexf* output, int forward, int benchmark);
25+
FFT_PLAN_T* make_fft_r2c(int size, float* input, complexf* output, int benchmark);
2526
void fft_execute(FFT_PLAN_T* plan);
2627
void fft_destroy(FFT_PLAN_T* plan);
2728

libcsdr.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,13 @@ void apply_precalculated_window_c(complexf* input, complexf* output, int size, f
12751275
}
12761276
}
12771277

1278+
void apply_precalculated_window_f(float* input, float* output, int size, float *windowt)
1279+
{
1280+
for(int i=0;i<size;i++) //@apply_precalculated_window_f
1281+
{
1282+
output[i] = input[i] * windowt[i];
1283+
}
1284+
}
12781285

12791286
void apply_window_f(float* input, float* output, int size, window_t window)
12801287
{

libcsdr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ void rational_resampler_get_lowpass_f(float* output, int output_size, int interp
142142
float *precalculate_window(int size, window_t window);
143143
void apply_window_c(complexf* input, complexf* output, int size, window_t window);
144144
void apply_precalculated_window_c(complexf* input, complexf* output, int size, float *windowt);
145+
void apply_precalculated_window_f(float* input, float* output, int size, float *windowt);
145146
void apply_window_f(float* input, float* output, int size, window_t window);
146147
void logpower_cf(complexf* input, float* output, int size, float add_db);
147148
void accumulate_power_cf(complexf* input, float* output, int size);

libcsdr_gpl.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,33 @@ float shift_addition_cc(complexf *input, complexf* output, int input_size, shift
5151
return starting_phase;
5252
}
5353

54+
float shift_addition_fc(float *input, complexf* output, int input_size, shift_addition_data_t d, float starting_phase)
55+
{
56+
//The original idea was taken from wdsp:
57+
//http://svn.tapr.org/repos_sdr_hpsdr/trunk/W5WC/PowerSDR_HPSDR_mRX_PS/Source/wdsp/shift.c
58+
59+
//However, this method introduces noise (from floating point rounding errors), which increases until the end of the buffer.
60+
//fprintf(stderr, "cosd=%g sind=%g\n", d.cosdelta, d.sindelta);
61+
float cosphi=cos(starting_phase);
62+
float sinphi=sin(starting_phase);
63+
float cosphi_last, sinphi_last;
64+
for(int i=0;i<input_size;i++) //@shift_addition_cc: work
65+
{
66+
iof(output,i)=cosphi*input[i];
67+
qof(output,i)=sinphi*input[i];
68+
//using the trigonometric addition formulas
69+
//cos(phi+delta)=cos(phi)cos(delta)-sin(phi)*sin(delta)
70+
cosphi_last=cosphi;
71+
sinphi_last=sinphi;
72+
cosphi=cosphi_last*d.cosdelta-sinphi_last*d.sindelta;
73+
sinphi=sinphi_last*d.cosdelta+cosphi_last*d.sindelta;
74+
}
75+
starting_phase+=d.rate*PI*input_size;
76+
while(starting_phase>PI) starting_phase-=2*PI; //@shift_addition_cc: normalize starting_phase
77+
while(starting_phase<-PI) starting_phase+=2*PI;
78+
return starting_phase;
79+
}
80+
5481
shift_addition_data_t shift_addition_init(float rate)
5582
{
5683
rate*=2;

libcsdr_gpl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ typedef struct shift_addition_data_s
3131
} shift_addition_data_t;
3232
shift_addition_data_t shift_addition_init(float rate);
3333
float shift_addition_cc(complexf *input, complexf* output, int input_size, shift_addition_data_t d, float starting_phase);
34+
float shift_addition_fc(float *input, complexf* output, int input_size, shift_addition_data_t d, float starting_phase);
3435
void shift_addition_cc_test(shift_addition_data_t d);
3536

3637
float agc_ff(float* input, float* output, int input_size, float reference, float attack_rate, float decay_rate, float max_gain, short hang_time, short attack_wait_time, float gain_filter_alpha, float last_gain);

0 commit comments

Comments
 (0)