/ csdr.c
csdr.c
   1  /*
   2  This software is part of libcsdr, a set of simple DSP routines for
   3  Software Defined Radio.
   4  
   5  Copyright (c) 2014, Andras Retzler <randras@sdr.hu>
   6  All rights reserved.
   7  
   8  Redistribution and use in source and binary forms, with or without
   9  modification, are permitted provided that the following conditions are met:
  10      * Redistributions of source code must retain the above copyright
  11        notice, this list of conditions and the following disclaimer.
  12      * Redistributions in binary form must reproduce the above copyright
  13        notice, this list of conditions and the following disclaimer in the
  14        documentation and/or other materials provided with the distribution.
  15      * Neither the name of the copyright holder nor the
  16        names of its contributors may be used to endorse or promote products
  17        derived from this software without specific prior written permission.
  18  
  19  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  20  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22  DISCLAIMED. IN NO EVENT SHALL ANDRAS RETZLER BE LIABLE FOR ANY
  23  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29  */
  30   
  31  #define _POSIX_C_SOURCE 199309L
  32  #define _BSD_SOURCE
  33  #define _GNU_SOURCE
  34  #include <stdio.h>
  35  #include <stdlib.h>
  36  #include <string.h>
  37  #include <limits.h>
  38  #include <sys/time.h>
  39  #include <sys/types.h>
  40  #include <sys/stat.h>
  41  #include <fcntl.h>
  42  #include <sys/ioctl.h>
  43  #include <unistd.h>
  44  #include <time.h>
  45  #include <stdarg.h>
  46  #include "libcsdr.h"
  47  #include "libcsdr_gpl.h"
  48  #include "ima_adpcm.h"
  49  #include <sched.h>
  50  #include <math.h>
  51  #include <strings.h>
  52  #include <errno.h>
  53  #include "fastddc.h"
  54  #include <assert.h>
  55  
  56  char usage[]=
  57  "csdr - a simple commandline tool for Software Defined Radio receiver DSP.\n\n"
  58  "usage: \n\n"
  59  "    csdr function_name <function_param1> <function_param2> [optional_param] ...\n\n"
  60  "list of functions:\n\n"
  61  "    convert_u8_f\n"
  62  "    convert_f_u8\n"
  63  "    convert_s8_f\n"
  64  "    convert_f_s8\n"
  65  "    convert_f_s16\n"
  66  "    convert_s16_f\n"
  67  "    convert_f_s24 [--bigendian]\n"
  68  "    convert_s24_f [--bigendian]\n"
  69  "    realpart_cf\n"
  70  "    clipdetect_ff\n"
  71  "    limit_ff [max_amplitude]\n"
  72  "    gain_ff <gain>\n"
  73  "    clone\n"
  74  "    none\n"
  75  "    yes_f <to_repeat> [buf_times]\n"
  76  "    detect_nan_ff\n"
  77  "    dump_f\n"
  78  "    shift_math_cc <rate>\n"
  79  "    shift_math_cc --fifo <fifo_path>\n"
  80  "    shift_addition_cc <rate>\n"
  81  "    shift_addition_cc --fifo <fifo_path>\n"
  82  "    shift_addition_cc_test\n"
  83  "    shift_table_cc <rate> [table_size]\n"
  84  "    shift_addition_fc <rate>\n"
  85  "    shift_addition_fc --fifo <fifo_path>\n"
  86  "    decimating_shift_addition_cc <rate> [decimation]\n"
  87  "    dcblock_ff\n"
  88  "    fastdcblock_ff\n"
  89  "    fmdemod_atan_cf\n"
  90  "    fmdemod_quadri_cf\n"
  91  "    fmdemod_quadri_novect_cf\n"
  92  "    deemphasis_wfm_ff <sample_rate> <tau>\n"
  93  "    deemphasis_nfm_ff <one_of_the_predefined_sample_rates>\n"
  94  "    amdemod_cf\n"
  95  "    amdemod_estimator_cf\n"
  96  "    fir_decimate_cc <decimation_factor> [transition_bw [window]]\n"
  97  "    fir_interpolate_cc <interpolation_factor> [transition_bw [window]]\n"
  98  "    firdes_lowpass_f <cutoff_rate> <length> [window [--octave]]\n"
  99  "    firdes_bandpass_c <low_cut> <high_cut> <length> [window [--octave]]\n"
 100  "    agc_ff [hang_time [reference [attack_rate [decay_rate [max_gain [attack_wait [filter_alpha]]]]]]]\n"
 101  "    fastagc_ff [block_size [reference]]\n"
 102  "    rational_resampler_ff <interpolation> <decimation> [transition_bw [window]]\n"
 103  "    old_fractional_decimator_ff <decimation_rate> [transition_bw [window]]\n"
 104  "    fractional_decimator_ff <decimation_rate> [num_poly_points ( [transition_bw [window]] | --prefilter )]\n"
 105  "    fft_cc <fft_size> <out_of_every_n_samples> [window [--octave] [--benchmark]]\n"
 106  "    fft_fc <fft_size> <out_of_every_n_samples> [window [--benchmark]]\n"
 107  "    logpower_cf [add_db]\n"
 108  "    fft_benchmark <fft_size> <fft_cycles> [--benchmark]\n"
 109  "    bandpass_fir_fft_cc <low_cut> <high_cut> <transition_bw> [window]\n"
 110  "    bandpass_fir_fft_cc --fifo <fifo_path> <transition_bw> [window]\n"
 111  "    encode_ima_adpcm_s16_u8\n"
 112  "    decode_ima_adpcm_u8_s16\n"
 113  "    compress_fft_adpcm_f_u8 <fft_size>\n"
 114  "    flowcontrol <data_rate> <reads_per_second>\n"
 115  "    through\n"
 116  "    dsb_fc [q_value]\n"
 117  "    convert_f_samperf <wait_for_this_sample> \n"
 118  "    fmmod_fc\n"
 119  "    fixed_amplitude_cc <new_amplitude>\n"
 120  "    mono2stereo_s16\n"
 121  "    setbuf <buffer_size>\n"
 122  "    fft_exchange_sides_ff <fft_size>\n"
 123  "    squelch_and_smeter_cc --fifo <squelch_fifo> --outfifo <smeter_fifo> <use_every_nth> <report_every_nth>\n"
 124  "    fifo <buffer_size> <number_of_buffers>\n"
 125  "    invert_u8_u8\n"
 126  "    rtty_line_decoder_u8_u8\n"
 127  "    rtty_baudot2ascii_u8_u8\n"
 128  "    serial_line_decoder_f_u8 <samples_per_bits> [databits [stopbits]]\n"
 129  "    octave_complex_c <samples_to_plot> <out_of_n_samples> [--2d]\n"
 130  "    timing_recovery_cc <algorithm> <decimation> [mu [max_error [--add_q [--output_error | --output_indexes | --octave <show_every_nth> | --octave_save <show_every_nth> <directory> ]]]] \n"
 131  "    psk31_varicode_encoder_u8_u8\n"
 132  "    psk31_varicode_decoder_u8_u8\n"
 133  "    differential_encoder_u8_u8\n"
 134  "    differential_decoder_u8_u8\n"
 135  "    dump_u8\n"
 136  "    psk_modulator_u8_c <n_psk>\n"
 137  "    psk31_interpolate_sine_cc <interpolation>\n"
 138  "    duplicate_samples_ntimes_u8_u8 <sample_size_bytes> <ntimes>\n"
 139  "    bpsk_costas_loop_cc <loop_bandwidth> <damping_factor> [--dd | --decision_directed] [--output_error | --output_dphase | --output_nco | --output_combined <error_file> <dphase_file> <nco_file>]\n"
 140  "    binary_slicer_f_u8\n"
 141  "    simple_agc_cc <rate> [reference [max_gain]]\n"
 142  "    firdes_peak_c <rate> <length> [window [--octave]]\n"
 143  "    peaks_fir_cc <taps_length> [peak_rate × N]\n"
 144  "    repeat_u8 <data_bytes × N>\n"
 145  "    uniform_noise_f\n"
 146  "    gaussian_noise_c\n"
 147  "    awgn_cc <snr_db> [--awgnfile <file>] [--snrshow]\n"
 148  "    pack_bits_8to1_u8_u8\n"
 149  "    pack_bits_1to8_u8_u8\n"
 150  "    firdes_pulse_shaping_filter_f (RRC <samples_per_symbol> <num_taps> <beta> | COSINE <samples_per_symbol>)\n"
 151  "    pulse_shaping_filter_cc (RRC <samples_per_symbol> <num_taps> <beta> | COSINE <samples_per_symbol>)\n"
 152  "    add_n_zero_samples_at_beginning_f <n_zero_samples>\n"
 153  "    generic_slicer_f_u8 <n_symbols>\n"
 154  "    plain_interpolate_cc <interpolation>\n"
 155  "    add_const_cc <i> <q>\n"
 156  "    tee <path> [buffers]\n"
 157  "    pll_cc (1 [alpha] |2 [bandwidth [damping_factor [ko [kd]]]])\n"
 158  "    pattern_search_u8_u8 <values_after> <pattern_values × N>\n" 
 159  "    dbpsk_decoder_c_u8\n" 
 160  "    bfsk_demod_cf <spacing> <filter_length>\n"
 161  "    normalized_timing_variance_u32_f <samples_per_symbol> <initial_sample_offset> [--debug]\n"
 162  "    ?<search_the_function_list>\n"
 163  "    ??<jump_to_function_docs_on_github>\n"
 164  "    =<evaluate_python_expression>\n"
 165  "    shift_addfast_cc <rate>   #only if system supports NEON \n"
 166  "    shift_unroll_cc <rate>\n"
 167  "    logaveragepower_cf <add_db> <fft_size> <avgnumber>\n"
 168  "    fft_one_side_ff <fft_size>\n"
 169  "    convert_f_samplerf <wait_for_this_sample>\n"
 170  "    add_dcoffset_cc\n"
 171  "    fastddc_fwd_cc <decimation> [transition_bw [window]]\n"
 172  "    fastddc_inv_cc <shift_rate> <decimation> [transition_bw [window]]\n"
 173  "    _fft2octave <fft_size>\n"
 174  "    convert_f_i16             #deprecated, use instead: convert_f_s16\n"
 175  "    convert_i16_f             #deprecated, use instead: convert_s16_f\n"
 176  "    floatdump_f               #deprecated, use instead: dump_f\n"
 177  "    mono2stereo_i16           #deprecated, use instead: mono2stereo_s16\n"
 178  "    decode_ima_adpcm_u8_i16   #deprecated, use instead: decode_ima_adpcm_u8_s16\n"
 179  "    encode_ima_adpcm_i16_u8   #deprecated, use instead: encode_ima_adpcm_i16_u8\n"
 180  "    \n"
 181  ;
 182  
 183  //change on 2015-08-29: we rather dynamically determine the bufsize
 184  //#define BUFSIZE (1024)
 185  //#define BIG_BUFSIZE (1024*16)
 186  //should be multiple of 16! (size of double complex)
 187  //also, keep in mind that shift_addition_cc works better the smaller this buffer is.
 188  
 189  int env_csdr_fixed_bufsize = 1024;
 190  int env_csdr_fixed_big_bufsize = 1024*16;
 191  int env_csdr_dynamic_bufsize_on = 0;
 192  int env_csdr_print_bufsizes = 0;
 193  int bigbufs = 0;
 194  
 195  //change on on 2015-08-29: we don't yield at all. fread() will do it if it blocks
 196  #define YIELD_EVERY_N_TIMES 3
 197  //#define TRY_YIELD if(++yield_counter%YIELD_EVERY_N_TIMES==0) sched_yield()
 198  #define TRY_YIELD fflush(stdout);sched_yield()
 199  //unsigned yield_counter=0;
 200  
 201  char **argv_global;
 202  int argc_global;
 203  
 204  int errhead()
 205  {
 206      fprintf(stderr, "%s%s%s: ", argv_global[0], ((argc_global>=2)?" ":""), ((argc_global>=2)?argv_global[1]:""));
 207  }
 208  
 209  int badsyntax(char* why)
 210  {
 211      if(why==0) fprintf(stderr, "%s", usage);
 212      else 
 213      {
 214          errhead();
 215          fprintf(stderr, "%s\n", why);
 216      }
 217      return -1;
 218  }
 219  
 220  int clipdetect_ff(float* input, int input_size)
 221  {
 222      for(int i=0;i<input_size;i++)
 223      {
 224          if(input[i]<-1.0) { errhead(); fprintf(stderr, "Signal value below -1.0!\n"); return -1; }
 225          if(input[i]>1.0) { errhead(); fprintf(stderr, "Signal value above 1.0!\n"); return 1; }
 226      }
 227      return 0;
 228  }
 229  
 230  int clone_(int bufsize_param)
 231  {
 232          unsigned char* clone_buffer;
 233          clone_buffer = (unsigned char*)malloc(bufsize_param*sizeof(unsigned char));
 234          for(;;)
 235          {
 236              fread(clone_buffer, sizeof(unsigned char), bufsize_param, stdin);
 237              fwrite(clone_buffer, sizeof(unsigned char), bufsize_param, stdout);
 238              TRY_YIELD;
 239          }
 240  }
 241  
 242  #define FREAD_U8    fread (input_buffer,    sizeof(unsigned char), the_bufsize, stdin)
 243  #define FWRITE_U8   fwrite (output_buffer,  sizeof(unsigned char), the_bufsize, stdout)
 244  #define FREAD_R     fread (input_buffer,    sizeof(float),      the_bufsize, stdin)
 245  #define FREAD_C     fread (input_buffer,    sizeof(float)*2,    the_bufsize, stdin)
 246  #define FWRITE_R    fwrite (output_buffer,  sizeof(float),      the_bufsize, stdout)
 247  #define FWRITE_C    fwrite (output_buffer,  sizeof(float)*2,    the_bufsize, stdout)
 248  #define FEOF_CHECK  if(feof(stdin)) return 0
 249  //#define BIG_FREAD_C fread(input_buffer, sizeof(float)*2, BIG_BUFSIZE, stdin)
 250  //#define BIG_FWRITE_C fwrite(output_buffer, sizeof(float)*2, BIG_BUFSIZE, stdout)
 251  
 252  int init_fifo(int argc, char *argv[])
 253  {
 254      if(argc>=4)
 255      {
 256          if(!strcmp(argv[2],"--fifo"))
 257          {
 258              errhead(); fprintf(stderr,"fifo control mode on\n");
 259              int fd = open(argv[3], O_RDONLY);
 260              int flags = fcntl(fd, F_GETFL, 0);
 261              fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 262              return fd;
 263          }
 264          else if(!strcmp(argv[2],"--fd"))  
 265          {
 266              //to use this:
 267              //1. Create a pipe(pipedesc) in your process.
 268              //2. fork() and execl() your process to run csdr, and give pipedesc[0] as parameter after --fd 
 269              //  Note: when forking, the child process will get a copy of the file descriptor table! That's why this 
 270              //  works at all, as file descriptor indexes are normally not transferable between processes, except for a *NIX socket way which is quite complicated... 
 271              //3. From your parent process, write into pipedesc[1].
 272              //This is implemented in ddcd, check there to see how to do it!
 273              int fd;
 274              if(sscanf(argv[3], "%d",&fd)<=0) return 0;
 275              errhead();
 276              fprintf(stderr,"fd control mode on, fd=%d\n", fd);
 277              int flags = fcntl(fd, F_GETFL, 0);
 278              fcntl(fd, F_SETFL, flags | O_NONBLOCK);
 279              return fd;
 280          }
 281      }
 282      return 0;
 283  }
 284  
 285  
 286  
 287  #define RFCTL_BUFSIZE 1024
 288  
 289  int read_fifo_ctl(int fd, char* format, ...)
 290  {
 291      if(!fd) return 0;
 292      static char buffer[RFCTL_BUFSIZE];
 293      static int buffer_index=0;
 294      int bytes_read=read(fd,buffer+buffer_index,(RFCTL_BUFSIZE-buffer_index)*sizeof(char));
 295      if(bytes_read<=0) return 0;
 296  
 297      int prev_newline_at=0;
 298      int last_newline_at=0;
 299      for(int i=0;i<buffer_index+bytes_read;i++)
 300      {
 301          if(buffer[i]=='\n')
 302          {
 303              prev_newline_at=last_newline_at;
 304              last_newline_at=i+1;
 305          }
 306      }
 307      if(last_newline_at)
 308      {
 309          //fprintf(stderr,"pna=%d lna=%d\n",prev_newline_at,last_newline_at);
 310          va_list vl;
 311          va_start(vl,format);
 312          vsscanf(buffer+prev_newline_at,format,vl);
 313          va_end(vl);
 314          memmove(buffer,buffer+last_newline_at,buffer_index+bytes_read-last_newline_at);
 315          buffer_index=bytes_read-last_newline_at;
 316          return 1;
 317      }
 318      else
 319      {
 320          buffer_index+=bytes_read;
 321          return 0;
 322      }
 323  }
 324  
 325  #define SETBUF_PREAMBLE "csdr"
 326  #define SETBUF_DEFAULT_BUFSIZE 1024
 327  #define STRINGIFY_VALUE(x) STRINGIFY_NAME(x)
 328  #define STRINGIFY_NAME(x) #x
 329  
 330  int getbufsize()
 331  {
 332      if(!env_csdr_dynamic_bufsize_on) return (bigbufs) ? env_csdr_fixed_big_bufsize : env_csdr_fixed_bufsize;
 333      int recv_first[2];
 334      fread(recv_first, sizeof(int), 2, stdin);
 335      if(memcmp(recv_first, SETBUF_PREAMBLE, sizeof(char)*4)!=0)
 336      { badsyntax("warning! Did not match preamble on the beginning of the stream. You should put \"csdr setbuf <buffer size>\" at the beginning of the chain! Falling back to default buffer size: " STRINGIFY_VALUE(SETBUF_DEFAULT_BUFSIZE)); return SETBUF_DEFAULT_BUFSIZE; }
 337      if(recv_first[1]<=0) { badsyntax("warning! Invalid buffer size." ); return 0; }
 338      return recv_first[1];
 339  }
 340  
 341  
 342  float* input_buffer;
 343  unsigned char* buffer_u8;
 344  float *output_buffer;
 345  short *buffer_i16;
 346  float *temp_f;
 347  int the_bufsize = 0;
 348  
 349  
 350  
 351  #define UNITROUND_UNIT 4
 352  
 353  int unitround(int what)
 354  {
 355      if(what<=0) return UNITROUND_UNIT;
 356      return ((what-1)&~(UNITROUND_UNIT-1))+UNITROUND_UNIT;
 357  }
 358  
 359  int initialize_buffers()
 360  {
 361      if(!(the_bufsize=getbufsize())) return 0;
 362      the_bufsize=unitround(the_bufsize);
 363      if(env_csdr_print_bufsizes) { errhead(); fprintf(stderr,"buffer size set to %d\n", the_bufsize); }
 364      input_buffer =  (float*)        malloc(the_bufsize*sizeof(float) * 2); //need the 2× because we might also put complex floats into it
 365      output_buffer = (float*)        malloc(the_bufsize*sizeof(float) * 2);
 366      buffer_u8 =     (unsigned char*)malloc(the_bufsize*sizeof(unsigned char));
 367      buffer_i16 =    (short*)        malloc(the_bufsize*sizeof(short));
 368      temp_f =        (float*)        malloc(the_bufsize*sizeof(float) * 4);
 369      if(the_bufsize<=4096) //this is hacky, should be done correctly
 370      {
 371          fcntl(STDIN_FILENO, F_SETPIPE_SZ,  4096);
 372          fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 4096);
 373      }
 374      return the_bufsize;
 375  }
 376  
 377  int sendbufsize(int size)
 378  {
 379      if(size<=4096)
 380      {
 381          fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 4096);
 382      }
 383      //The first word is a preamble, "csdr".
 384      //If the next csdr process detects it, sets the buffer size according to the second word
 385      if(!env_csdr_dynamic_bufsize_on) return env_csdr_fixed_bufsize;
 386      if(env_csdr_print_bufsizes) { errhead(); fprintf(stderr,"next process proposed input buffer size is %d\n", size); }
 387      int send_first[2];
 388      memcpy((char*)send_first, SETBUF_PREAMBLE, 4*sizeof(char));
 389      send_first[1] = size;
 390      fwrite(send_first, sizeof(int), 2, stdout);
 391      return size;
 392  }
 393  
 394  int parse_env()
 395  {
 396      char* envtmp;
 397      envtmp=getenv("CSDR_DYNAMIC_BUFSIZE_ON");
 398      //fprintf(stderr, "envtmp: %s\n",envtmp);
 399      if(envtmp)
 400      {
 401          env_csdr_dynamic_bufsize_on = !!atoi(envtmp);
 402          env_csdr_fixed_bufsize = 0;
 403      }
 404      else
 405      {
 406          envtmp=getenv("CSDR_FIXED_BUFSIZE");
 407          if(envtmp)
 408          {
 409              env_csdr_fixed_big_bufsize = env_csdr_fixed_bufsize = atoi(envtmp);
 410          }
 411      }
 412      envtmp=getenv("CSDR_PRINT_BUFSIZES");
 413      if(envtmp)
 414      {
 415          env_csdr_print_bufsizes = atoi(envtmp);
 416      }
 417  }
 418  
 419  int main(int argc, char *argv[])
 420  {
 421      parse_env();
 422      argv_global=argv;
 423      argc_global=argc;
 424      if(argc<=1) return badsyntax(0);
 425      if(!strcmp(argv[1],"--help")) return badsyntax(0);
 426  
 427      fcntl(STDIN_FILENO, F_SETPIPE_SZ, 65536*32);
 428      fcntl(STDOUT_FILENO, F_SETPIPE_SZ, 65536*32);
 429      //fprintf(stderr, "csdr: F_SETPIPE_SZ\n");
 430  
 431      if(!strcmp(argv[1],"setbuf"))
 432      {
 433          if(argc<=2) return badsyntax("need required parameter (buffer size)");
 434          sscanf(argv[2],"%d",&the_bufsize);
 435          if(the_bufsize<=0) return badsyntax("buffer size <= 0 is invalid");
 436          sendbufsize(the_bufsize);
 437          clone_(the_bufsize); //After sending the buffer size out, just copy stdin to stdout
 438      }
 439  
 440      if(!strcmp(argv[1],"clone") || !strcmp(argv[1],"REM"))
 441      {
 442          if(!sendbufsize(initialize_buffers())) return -2;
 443          clone_(the_bufsize);
 444      }
 445  #define SET_NONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK)
 446  
 447      if(!strcmp(argv[1],"fifo"))
 448      {
 449          if(!sendbufsize(initialize_buffers())) return -2;
 450  
 451          int fifo_buffer_size;
 452          if(argc<=2) return badsyntax("need required parameter (buffer_size)");
 453          sscanf(argv[2],"%d",&fifo_buffer_size);
 454          int fifo_num_buffers;
 455          if(argc<=3) return badsyntax("need required parameter (number of buffers)");
 456          sscanf(argv[3],"%d",&fifo_num_buffers);
 457  
 458          char** fifo_buffers = (char**)malloc(sizeof(char*)*fifo_num_buffers);
 459          for(int i=0;i<fifo_num_buffers;i++) fifo_buffers[i]=(char*)malloc(sizeof(char)*fifo_buffer_size);
 460  
 461          SET_NONBLOCK(STDIN_FILENO);
 462          SET_NONBLOCK(STDOUT_FILENO);
 463  
 464          fd_set read_fds;
 465          FD_ZERO(&read_fds);
 466          FD_SET(STDIN_FILENO, &read_fds);
 467          fd_set write_fds;
 468          FD_ZERO(&write_fds);
 469          FD_SET(STDOUT_FILENO, &write_fds);
 470  
 471          int highfd = ((STDOUT_FILENO > STDIN_FILENO) ? STDOUT_FILENO : STDIN_FILENO) + 1;
 472  
 473          int fifo_actual_buffer_wr = fifo_num_buffers - 1;
 474          int fifo_actual_buffer_rd = 0;
 475          int fifo_actual_buffer_wr_pos = 0;
 476          int fifo_actual_buffer_rd_pos = 0;
 477          int fifo_error = 0;
 478          int fifo_overrun_shown = 0;
 479  
 480          for(;;)
 481          {
 482              select(highfd, &read_fds, NULL, NULL, NULL);
 483  
 484              //try to read until buffer is full
 485              if(FD_ISSET(STDIN_FILENO, &read_fds)) for(;;)
 486              {
 487                  int read_bytes=read(STDIN_FILENO, fifo_buffers[fifo_actual_buffer_rd]+fifo_actual_buffer_rd_pos, fifo_buffer_size-fifo_actual_buffer_rd_pos);
 488                  //fprintf(stderr, "r %d %d | %d %d\n", read_bytes, fifo_buffer_size-fifo_actual_buffer_rd_pos, fifo_actual_buffer_rd, fifo_actual_buffer_rd_pos);
 489                  if(!read_bytes || ((read_bytes<0)&&(fifo_error=read_bytes)) ) break;
 490                  fifo_actual_buffer_rd_pos+=read_bytes;
 491                  if(!((fifo_actual_buffer_rd==fifo_actual_buffer_wr-1)||(fifo_actual_buffer_wr==0&&fifo_actual_buffer_rd==fifo_num_buffers-1)))
 492                  {
 493                      if(fifo_actual_buffer_rd_pos==fifo_buffer_size)
 494                      {
 495                          fifo_overrun_shown = 0;
 496                          fifo_actual_buffer_rd++;
 497                          fifo_actual_buffer_rd_pos = 0;
 498                          if(fifo_actual_buffer_rd>=fifo_num_buffers) fifo_actual_buffer_rd=0;
 499                      }
 500                  }
 501                  else
 502                  {
 503                      if(fifo_actual_buffer_rd_pos==fifo_buffer_size)
 504                      {
 505                          fifo_actual_buffer_rd_pos = 0; //rewrite same buffer
 506                          if(!fifo_overrun_shown) { fifo_overrun_shown=1; errhead(); fprintf(stderr, "circular buffer full, dropping samples\n"); }
 507                      }
 508                  }
 509              }
 510              //try to write until buffer is empty
 511              if(FD_ISSET(STDOUT_FILENO, &write_fds)) for(;;)
 512              {
 513                  if(fifo_actual_buffer_wr == fifo_actual_buffer_rd) break;
 514                  int written_bytes=write(STDOUT_FILENO, fifo_buffers[fifo_actual_buffer_wr]+fifo_actual_buffer_wr_pos, fifo_buffer_size-fifo_actual_buffer_wr_pos);
 515                  //fprintf(stderr, "w %d %d | %d %d\n", written_bytes, fifo_buffer_size-fifo_actual_buffer_wr_pos, fifo_actual_buffer_wr, fifo_actual_buffer_wr_pos);
 516                  if(!written_bytes || ((written_bytes<0)&&(fifo_error=written_bytes)) ) break;
 517                  fifo_actual_buffer_wr_pos+=written_bytes;
 518                  if(fifo_actual_buffer_wr_pos==fifo_buffer_size)
 519                  {
 520                      fifo_actual_buffer_wr++;
 521                      fifo_actual_buffer_wr_pos = 0;
 522                      if(fifo_actual_buffer_wr>=fifo_num_buffers) fifo_actual_buffer_wr=0;
 523                  }
 524  
 525              }
 526              if(fifo_error&&errno!=11) { errhead(); fprintf(stderr,"fifo_error (%d)", errno); return -1; }
 527          }
 528  
 529          return -1;
 530  
 531      }
 532  
 533  
 534      if(!strcmp(argv[1],"convert_u8_f"))
 535      {
 536          if(!sendbufsize(initialize_buffers())) return -2;
 537          for(;;)
 538          {
 539              FEOF_CHECK;
 540              fread(buffer_u8, sizeof(unsigned char), the_bufsize, stdin);
 541              convert_u8_f(buffer_u8, output_buffer, the_bufsize);
 542              FWRITE_R;
 543              TRY_YIELD;
 544          }
 545      }
 546      if(!strcmp(argv[1],"convert_f_u8")) //not tested
 547      {
 548          if(!sendbufsize(initialize_buffers())) return -2;
 549          for(;;)
 550          {
 551              FEOF_CHECK;
 552              FREAD_R;
 553              convert_f_u8(input_buffer, buffer_u8, the_bufsize);
 554              fwrite(buffer_u8, sizeof(unsigned char), the_bufsize, stdout);
 555              TRY_YIELD;
 556          }
 557      }
 558      if(!strcmp(argv[1],"convert_s8_f"))
 559      {
 560          if(!sendbufsize(initialize_buffers())) return -2;
 561          for(;;)
 562          {
 563              FEOF_CHECK;
 564              fread((signed char*)buffer_u8, sizeof(signed char), the_bufsize, stdin);
 565              convert_s8_f((signed char*)buffer_u8, output_buffer, the_bufsize);
 566              FWRITE_R;
 567              TRY_YIELD;
 568          }
 569      }
 570      if(!strcmp(argv[1],"convert_f_s8")) //not tested
 571      {
 572          if(!sendbufsize(initialize_buffers())) return -2;
 573          for(;;)
 574          {
 575              FEOF_CHECK;
 576              FREAD_R;
 577              convert_f_s8(input_buffer, (signed char*)buffer_u8, the_bufsize);
 578              fwrite((signed char*)buffer_u8, sizeof(signed char), the_bufsize, stdout);
 579              TRY_YIELD;
 580          }
 581      }
 582      if((!strcmp(argv[1],"convert_f_i16")) || (!strcmp(argv[1],"convert_f_s16")))
 583      {
 584          if(!sendbufsize(initialize_buffers())) return -2;
 585          for(;;)
 586          {
 587              FEOF_CHECK;
 588              FREAD_R;
 589              convert_f_i16(input_buffer, buffer_i16, the_bufsize);
 590              fwrite(buffer_i16, sizeof(short), the_bufsize, stdout);
 591              TRY_YIELD;
 592          }
 593      }
 594      if((!strcmp(argv[1],"convert_i16_f")) || (!strcmp(argv[1],"convert_s16_f")))
 595      {
 596          if(!sendbufsize(initialize_buffers())) return -2;
 597          for(;;)
 598          {
 599              FEOF_CHECK;
 600              fread(buffer_i16, sizeof(short), the_bufsize, stdin);
 601              convert_i16_f(buffer_i16, output_buffer, the_bufsize);
 602              FWRITE_R;
 603              TRY_YIELD;
 604          }
 605      }
 606      if(!strcmp(argv[1],"convert_f_s24"))
 607      {
 608          int bigendian = (argc>2) && (!strcmp(argv[2],"--bigendian"));
 609          unsigned char* s24buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*3);
 610          if(!sendbufsize(initialize_buffers())) return -2;
 611          for(;;)
 612          {
 613              FEOF_CHECK;
 614              FREAD_R;
 615              convert_f_s24(input_buffer, s24buffer, the_bufsize, bigendian);
 616              fwrite(s24buffer, sizeof(unsigned char)*3, the_bufsize, stdout);
 617              TRY_YIELD;
 618          }
 619      }
 620      if(!strcmp(argv[1],"convert_s24_f"))
 621      {
 622          int bigendian = (argc>2) && (!strcmp(argv[2],"--bigendian"));
 623          unsigned char* s24buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*3);
 624          if(!sendbufsize(initialize_buffers())) return -2;
 625          for(;;)
 626          {
 627              FEOF_CHECK;
 628              fread(s24buffer, sizeof(unsigned char)*3, the_bufsize, stdin);
 629              convert_s24_f(s24buffer, output_buffer, the_bufsize, bigendian);
 630              FWRITE_R;
 631              TRY_YIELD;
 632          }
 633      }
 634      if(!strcmp(argv[1],"realpart_cf"))
 635      {
 636          if(!sendbufsize(initialize_buffers())) return -2;
 637          for(;;)
 638          {
 639              FEOF_CHECK;
 640              FREAD_C;
 641              for(int i=0;i<the_bufsize;i++) output_buffer[i]=iof(input_buffer,i);
 642              FWRITE_R;
 643              TRY_YIELD;
 644          }
 645      }
 646      if(!strcmp(argv[1],"clipdetect_ff"))
 647      {
 648          if(!sendbufsize(initialize_buffers())) return -2;
 649          for(;;)
 650          {
 651              FEOF_CHECK;
 652              FREAD_R;
 653              clipdetect_ff(input_buffer, the_bufsize);
 654              fwrite(input_buffer, sizeof(float), the_bufsize, stdout);
 655              TRY_YIELD;
 656          }
 657      }
 658      if(!strcmp(argv[1],"gain_ff"))
 659      {
 660          if(argc<=2) return badsyntax("need required parameter (gain)");
 661          float gain;
 662          sscanf(argv[2],"%g",&gain);
 663          if(!sendbufsize(initialize_buffers())) return -2;
 664          for(;;)
 665          {
 666              FEOF_CHECK;
 667              FREAD_R;
 668              gain_ff(input_buffer, output_buffer, the_bufsize, gain);
 669              FWRITE_R;
 670              TRY_YIELD;
 671          }
 672      }
 673      if(!strcmp(argv[1],"limit_ff"))
 674      {
 675          float max_amplitude=1.0;
 676          if(argc>=3) sscanf(argv[2],"%g",&max_amplitude);
 677          if(!sendbufsize(initialize_buffers())) return -2;
 678          for(;;)
 679          {
 680              FEOF_CHECK;
 681              FREAD_R;
 682              limit_ff(input_buffer, output_buffer, the_bufsize, max_amplitude);
 683              FWRITE_R;
 684              TRY_YIELD;
 685          }
 686      }
 687      if(!strcmp(argv[1],"yes_f"))
 688      {
 689          if(argc<=2) return badsyntax("need required parameter (to_repeat)");
 690          float to_repeat;
 691          sscanf(argv[2],"%g",&to_repeat);
 692          int buf_times = 0;
 693          if(argc>=4) sscanf(argv[3],"%d",&buf_times);
 694          if(!sendbufsize(initialize_buffers())) return -2;
 695          for(int i=0;i<the_bufsize;i++) output_buffer[i]=to_repeat;
 696          for(int i=0;(!buf_times)||i<buf_times;i++)
 697          {
 698              fwrite(output_buffer, sizeof(float), the_bufsize, stdout);
 699              TRY_YIELD;
 700          }
 701          return 0;
 702      }
 703      if(!strcmp(argv[1],"shift_math_cc"))
 704      {
 705          if(argc<=2) return badsyntax("need required parameter (rate)");
 706          float starting_phase=0;
 707          float rate;
 708          sscanf(argv[2],"%g",&rate);
 709          if(!sendbufsize(initialize_buffers())) return -2;
 710          for(;;)
 711          {
 712              FEOF_CHECK;
 713              if(!FREAD_C) break;
 714              starting_phase=shift_math_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, rate, starting_phase);
 715              FWRITE_C;
 716              TRY_YIELD;
 717          }
 718          return 0;
 719      }
 720      //speed tests:
 721      //csdr yes_f 1 1000000 | time csdr shift_math_cc 0.2 >/dev/null
 722      //csdr yes_f 1 1000000 | time csdr shift_addition_cc 0.2 >/dev/null
 723      //csdr yes_f 1 1000000 | time csdr shift_table_cc 0.2 >/dev/null
 724  
 725      if(!strcmp(argv[1],"shift_table_cc"))
 726      {
 727          bigbufs=1;
 728          if(argc<=2) return badsyntax("need required parameter (rate)");
 729          float starting_phase=0;
 730          float rate;
 731          int table_size=65536;
 732          sscanf(argv[2],"%g",&rate);
 733          if(argc>3) sscanf(argv[3],"%d",&table_size);
 734          if(!sendbufsize(initialize_buffers())) return -2;
 735          shift_table_data_t table_data=shift_table_init(table_size);
 736          errhead();
 737          fprintf(stderr,"LUT initialized\n");
 738          for(;;)
 739          {
 740              FEOF_CHECK;
 741              if(!FREAD_C) break;
 742              starting_phase=shift_table_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, rate, table_data, starting_phase);
 743              FWRITE_C;
 744              TRY_YIELD;
 745          }
 746          return 0;
 747      }
 748  
 749      if(!strcmp(argv[1],"shift_addfast_cc"))
 750      {
 751          bigbufs=1;
 752  
 753          float starting_phase=0;
 754          float rate;
 755  
 756          int fd;
 757          if(fd=init_fifo(argc,argv))
 758          {
 759              while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000);
 760          }
 761          else
 762          {
 763              if(argc<=2) return badsyntax("need required parameter (rate)"); 
 764              sscanf(argv[2],"%g",&rate);
 765          }
 766  
 767          if(!sendbufsize(initialize_buffers())) return -2;
 768          for(;;)
 769          {
 770              shift_addfast_data_t data=shift_addfast_init(rate);
 771              errhead();
 772              fprintf(stderr,"reinitialized to %g\n",rate);
 773              int remain, current_size;
 774              float* ibufptr;
 775              float* obufptr;
 776              for(;;)
 777              {
 778                  FEOF_CHECK;
 779                  if(!FREAD_C) break;
 780                  remain=the_bufsize;
 781                  ibufptr=input_buffer;
 782                  obufptr=output_buffer;
 783                  while(remain)
 784                  {
 785                      current_size=(remain>1024)?1024:remain;
 786                      starting_phase=shift_addfast_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, &data, starting_phase);
 787                      ibufptr+=current_size*2;
 788                      obufptr+=current_size*2;
 789                      remain-=current_size;
 790                  }
 791                  FWRITE_C;
 792                  if(read_fifo_ctl(fd,"%g\n",&rate)) break;
 793                  TRY_YIELD;
 794              }
 795          }
 796          return 0;
 797      }
 798  
 799  
 800      if(!strcmp(argv[1],"shift_unroll_cc"))
 801      {
 802          bigbufs=1;
 803  
 804          float starting_phase=0;
 805          float rate;
 806  
 807          int fd;
 808          if(fd=init_fifo(argc,argv))
 809          {
 810              while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000);
 811          }
 812          else
 813          {
 814              if(argc<=2) return badsyntax("need required parameter (rate)"); 
 815              sscanf(argv[2],"%g",&rate);
 816          }
 817  
 818          if(!sendbufsize(initialize_buffers())) return -2;
 819          for(;;)
 820          {
 821              shift_unroll_data_t data=shift_unroll_init(rate, 1024);
 822              errhead();
 823              fprintf(stderr,"reinitialized to %g\n",rate);
 824              int remain, current_size;
 825              float* ibufptr;
 826              float* obufptr;
 827              for(;;)
 828              {
 829                  FEOF_CHECK;
 830                  if(!FREAD_C) break;
 831                  remain=the_bufsize;
 832                  ibufptr=input_buffer;
 833                  obufptr=output_buffer;
 834                  while(remain)
 835                  {
 836                      current_size=(remain>1024)?1024:remain;
 837                      starting_phase=shift_unroll_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, &data, starting_phase);
 838                      ibufptr+=current_size*2;
 839                      obufptr+=current_size*2;
 840                      remain-=current_size;
 841                  }
 842                  FWRITE_C;
 843                  if(read_fifo_ctl(fd,"%g\n",&rate)) break;
 844                  TRY_YIELD;
 845              }
 846          }
 847          return 0;
 848      }
 849  
 850  #ifdef LIBCSDR_GPL
 851      if(!strcmp(argv[1],"decimating_shift_addition_cc"))
 852      {
 853          bigbufs=1;
 854          if(argc<=2) return badsyntax("need required parameter (rate)");
 855          float starting_phase=0;
 856          float rate;
 857          int decimation=1;
 858          sscanf(argv[2],"%g",&rate);
 859          if(argc>3) sscanf(argv[3],"%d",&decimation);
 860          if(!initialize_buffers()) return -2;
 861          sendbufsize(the_bufsize/decimation);
 862          shift_addition_data_t d=decimating_shift_addition_init(rate, decimation);
 863          decimating_shift_addition_status_t s;
 864          s.decimation_remain=0;
 865          s.starting_phase=0;
 866          for(;;)
 867          {
 868              FEOF_CHECK;
 869              if(!FREAD_C) break;
 870              s=decimating_shift_addition_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, d, decimation, s);
 871              fwrite(output_buffer, sizeof(float)*2, s.output_size, stdout);
 872              TRY_YIELD;
 873          }
 874          return 0;
 875      }
 876  
 877      if(!strcmp(argv[1],"shift_addition_cc"))
 878      {
 879          bigbufs=1;
 880  
 881          float starting_phase=0;
 882          float rate;
 883  
 884          int fd;
 885          if(fd=init_fifo(argc,argv))
 886          {
 887              while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000);
 888          }
 889          else
 890          {
 891              if(argc<=2) return badsyntax("need required parameter (rate)");
 892              sscanf(argv[2],"%g",&rate);
 893          }
 894  
 895          if(!sendbufsize(initialize_buffers())) return -2;
 896          for(;;)
 897          {
 898              shift_addition_data_t data=shift_addition_init(rate);
 899              errhead();
 900              fprintf(stderr,"reinitialized to %g\n",rate);
 901              int remain, current_size;
 902              float* ibufptr;
 903              float* obufptr;
 904              for(;;)
 905              {
 906                  FEOF_CHECK;
 907                  if(!FREAD_C) break;
 908                  remain=the_bufsize;
 909                  ibufptr=input_buffer;
 910                  obufptr=output_buffer;
 911                  while(remain)
 912                  {
 913                      current_size=(remain>1024)?1024:remain;
 914                      starting_phase=shift_addition_cc((complexf*)ibufptr, (complexf*)obufptr, current_size, data, starting_phase);
 915                      ibufptr+=current_size*2;
 916                      obufptr+=current_size*2;
 917                      remain-=current_size;
 918                  }
 919                  FWRITE_C;
 920                  if(read_fifo_ctl(fd,"%g\n",&rate)) break;
 921                  TRY_YIELD;
 922              }
 923          }
 924          return 0;
 925      }
 926  
 927      if(!strcmp(argv[1],"shift_addition_cc_test"))
 928      {
 929          if(argc<=2) return badsyntax("need required parameter (rate)");
 930          float rate;
 931          sscanf(argv[2],"%g",&rate);
 932          //if(initialize_buffers()) return -2; //most likely we don't need this here
 933          shift_addition_data_t data=shift_addition_init(rate);
 934          shift_addition_cc_test(data);
 935          return 0;
 936      }
 937  #endif
 938      if(!strcmp(argv[1],"dcblock_ff"))
 939      {
 940          static dcblock_preserve_t dcp; //will be 0 as .bss is set to 0
 941          if(!sendbufsize(initialize_buffers())) return -2;
 942          for(;;)
 943          {
 944              FEOF_CHECK;
 945              FREAD_R;
 946              dcp=dcblock_ff(input_buffer, output_buffer, the_bufsize, 0, dcp);
 947              FWRITE_R;
 948              TRY_YIELD;
 949          }
 950      }
 951  
 952      if(!strcmp(argv[1],"fastdcblock_ff"))
 953      {
 954          int dcblock_bufsize=SETBUF_DEFAULT_BUFSIZE;
 955          if(argc>=3) sscanf(argv[2],"%d",&dcblock_bufsize);
 956          float* dcblock_buffer=(float*)malloc(sizeof(float)*dcblock_bufsize);
 957          static float last_dc_level=0.0;
 958          getbufsize(); //it is just dummy
 959          sendbufsize(dcblock_bufsize);
 960          for(;;)
 961          {
 962              FEOF_CHECK;
 963              fread(dcblock_buffer, sizeof(float), dcblock_bufsize, stdin);
 964              last_dc_level=fastdcblock_ff(dcblock_buffer, dcblock_buffer, dcblock_bufsize, last_dc_level);
 965              fwrite(dcblock_buffer, sizeof(float), dcblock_bufsize, stdout);
 966              TRY_YIELD;
 967          }
 968      }
 969  
 970      if(!strcmp(argv[1],"fmdemod_atan_cf"))
 971      {
 972          if(!sendbufsize(initialize_buffers())) return -2;
 973          float last_phase=0;
 974          for(;;)
 975          {
 976              FEOF_CHECK;
 977              FREAD_C;
 978              if(feof(stdin)) return 0;
 979              last_phase=fmdemod_atan_cf((complexf*)input_buffer, output_buffer, the_bufsize, last_phase);
 980              FWRITE_R;
 981              TRY_YIELD;
 982          }
 983      }
 984      if(!strcmp(argv[1],"fmdemod_quadri_cf"))
 985      {
 986          if(!sendbufsize(initialize_buffers())) return -2;
 987          complexf last_sample;
 988          last_sample.i=0.;
 989          last_sample.q=0.;
 990          for(;;)
 991          {
 992              FEOF_CHECK;
 993              FREAD_C;
 994              last_sample=fmdemod_quadri_cf((complexf*)input_buffer, output_buffer, the_bufsize, temp_f, last_sample);
 995              FWRITE_R;
 996              TRY_YIELD;
 997          }
 998      }
 999      if(!strcmp(argv[1],"fmdemod_quadri_novect_cf"))
1000      {
1001          if(!sendbufsize(initialize_buffers())) return -2;
1002          complexf last_sample;
1003          last_sample.i=0.;
1004          last_sample.q=0.;
1005          for(;;)
1006          {
1007              FEOF_CHECK;
1008              FREAD_C;
1009              last_sample=fmdemod_quadri_novect_cf((complexf*)input_buffer, output_buffer, the_bufsize, last_sample);
1010              FWRITE_R;
1011              TRY_YIELD;
1012          }
1013      }
1014      if(!strcmp(argv[1],"deemphasis_wfm_ff"))
1015      {
1016          if(argc<=3) return badsyntax("need required parameters (sample rate, tau)");
1017          if(!sendbufsize(initialize_buffers())) return -2;
1018          int sample_rate;
1019          sscanf(argv[2],"%d",&sample_rate);
1020          float tau;
1021          sscanf(argv[3],"%g",&tau);
1022          errhead(); fprintf(stderr,"tau = %g, sample_rate = %d\n",tau,sample_rate);
1023          float last_output=0;
1024          for(;;)
1025          {
1026              FEOF_CHECK;
1027              FREAD_R;
1028              last_output=deemphasis_wfm_ff(input_buffer, output_buffer, the_bufsize, tau, sample_rate, last_output);
1029              FWRITE_R;
1030              TRY_YIELD;
1031          }
1032      }
1033  
1034      if(!strcmp(argv[1],"detect_nan_ff"))
1035      {
1036          if(!sendbufsize(initialize_buffers())) return -2;
1037          for(;;)
1038          {
1039              FEOF_CHECK;
1040              FREAD_R;
1041              int nan_detect=0;
1042              for(int i=0; i<the_bufsize;i++)
1043              {
1044                  if(is_nan(input_buffer[i]))
1045                  {
1046                      nan_detect=1;
1047                      break;
1048                  }
1049              }
1050              if(nan_detect) { errhead(); fprintf(stderr, "NaN detected!\n"); }
1051              fwrite(input_buffer, sizeof(float), the_bufsize, stdout);
1052              TRY_YIELD;
1053          }
1054      }
1055  
1056      if(!strcmp(argv[1],"floatdump_f") || !strcmp(argv[1],"dump_f"))
1057      {
1058          if(!sendbufsize(initialize_buffers())) return -2;
1059          for(;;)
1060          {
1061              FEOF_CHECK;
1062              FREAD_R;
1063              for(int i=0; i<the_bufsize;i++) printf("%g ",input_buffer[i]);
1064              TRY_YIELD;
1065          }
1066  
1067      }
1068      if(!strcmp(argv[1],"deemphasis_nfm_ff"))
1069      {
1070          if(argc<=2) return badsyntax("need required parameter (sample rate)");
1071          int sample_rate;
1072          sscanf(argv[2],"%d",&sample_rate);
1073  
1074          if(!sendbufsize(initialize_buffers())) return -2; //maybe we should take a /2 of bufsize over here
1075  
1076          int processed=0;
1077          for(;;)
1078          {
1079              FEOF_CHECK;
1080              fread(input_buffer+the_bufsize-processed, sizeof(float), processed, stdin);
1081              processed=deemphasis_nfm_ff(input_buffer, output_buffer, the_bufsize, sample_rate);
1082              if(!processed) return badsyntax("deemphasis_nfm_ff: invalid sample rate (this function works only with specific sample rates).");
1083              memmove(input_buffer,input_buffer+processed,(the_bufsize-processed)*sizeof(float)); //memmove lets the source and destination overlap
1084              fwrite(output_buffer, sizeof(float), processed, stdout);
1085              TRY_YIELD;
1086          }
1087      }
1088      if(!strcmp(argv[1],"amdemod_cf"))
1089      {
1090          if(!sendbufsize(initialize_buffers())) return -2;
1091  
1092          for(;;)
1093          {
1094              FEOF_CHECK;
1095              FREAD_C;
1096              amdemod_cf((complexf*)input_buffer, output_buffer, the_bufsize);
1097              FWRITE_R;
1098              TRY_YIELD;
1099          }
1100      }
1101      if(!strcmp(argv[1],"amdemod_estimator_cf"))
1102      {
1103          if(!sendbufsize(initialize_buffers())) return -2;
1104          for(;;)
1105          {
1106              FEOF_CHECK;
1107              FREAD_C;
1108              amdemod_estimator_cf((complexf*)input_buffer, output_buffer, the_bufsize, 0., 0.);
1109              FWRITE_R;
1110              TRY_YIELD;
1111          }
1112      }
1113  
1114      if(!strcmp(argv[1],"fir_decimate_cc"))
1115      {
1116          bigbufs=1;
1117  
1118          if(argc<=2) return badsyntax("need required parameter (decimation factor)");
1119  
1120          int factor;
1121          sscanf(argv[2],"%d",&factor);
1122  
1123          float transition_bw = 0.05;
1124          if(argc>=4) sscanf(argv[3],"%g",&transition_bw);
1125  
1126          window_t window = WINDOW_DEFAULT;
1127          if(argc>=5)
1128          {
1129              window=firdes_get_window_from_string(argv[4]);
1130          }
1131          else fprintf(stderr,"fir_decimate_cc: window = %s\n",firdes_get_string_from_window(window));
1132  
1133          int taps_length=firdes_filter_len(transition_bw);
1134          fprintf(stderr,"fir_decimate_cc: taps_length = %d\n",taps_length);
1135  
1136          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
1137          //fprintf(stderr, "env_csdr_fixed_big_bufsize = %d\n", env_csdr_fixed_big_bufsize);
1138  
1139          if(!initialize_buffers()) return -2;
1140          sendbufsize(the_bufsize/factor);
1141  
1142  
1143          int padded_taps_length = taps_length;
1144          float *taps;
1145  #define NEON_ALIGNMENT (4*4*2)
1146  #ifdef NEON_OPTS
1147          errhead(); fprintf(stderr,"taps_length = %d\n", taps_length);
1148          padded_taps_length = taps_length+(NEON_ALIGNMENT/4)-1 - ((taps_length+(NEON_ALIGNMENT/4)-1)%(NEON_ALIGNMENT/4));
1149          errhead(); fprintf(stderr,"padded_taps_length = %d\n", padded_taps_length);
1150  
1151          taps = (float*) (float*)malloc((padded_taps_length+NEON_ALIGNMENT)*sizeof(float));
1152          errhead(); fprintf(stderr,"taps = %x\n", taps);
1153          taps =  (float*)((((unsigned)taps)+NEON_ALIGNMENT-1) & ~(NEON_ALIGNMENT-1));
1154          errhead(); fprintf(stderr,"NEON aligned taps = %x\n", taps);
1155          for(int i=0;i<padded_taps_length-taps_length;i++) taps[taps_length+i]=0;
1156  #else
1157          taps=(float*)malloc(taps_length*sizeof(float));
1158  #endif
1159  
1160          firdes_lowpass_f(taps,taps_length,0.5/(float)factor,window);
1161  
1162          int input_skip=0;
1163          int output_size=0;
1164          FREAD_C;
1165          for(;;)
1166          {
1167              FEOF_CHECK;
1168              output_size=fir_decimate_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, factor, taps, padded_taps_length);
1169              //fprintf(stderr, "os %d\n",output_size);
1170              fwrite(output_buffer, sizeof(complexf), output_size, stdout);
1171              TRY_YIELD;
1172              input_skip=factor*output_size;
1173              memmove((complexf*)input_buffer,((complexf*)input_buffer)+input_skip,(the_bufsize-input_skip)*sizeof(complexf)); //memmove lets the source and destination overlap
1174              fread(((complexf*)input_buffer)+(the_bufsize-input_skip), sizeof(complexf), input_skip, stdin);
1175              //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));
1176          }
1177      }
1178  
1179      if(!strcmp(argv[1],"fir_interpolate_cc"))
1180      {
1181          bigbufs=1;
1182  
1183          if(argc<=2) return badsyntax("need required parameter (interpolation factor)");
1184  
1185          int factor;
1186          sscanf(argv[2],"%d",&factor);
1187          assert(factor >= 1);
1188  
1189          float transition_bw = 0.05;
1190          if(argc>=4) sscanf(argv[3],"%g",&transition_bw);
1191          assert(transition_bw >= 0 && transition_bw < 1.);
1192  
1193          window_t window = WINDOW_DEFAULT;
1194          if(argc>=5)
1195          {
1196              window=firdes_get_window_from_string(argv[4]);
1197          }
1198          else {errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window));}
1199  
1200          int taps_length=firdes_filter_len(transition_bw);
1201          errhead(); fprintf(stderr,"taps_length = %d\n",taps_length);
1202          assert(taps_length > 0);
1203  
1204          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
1205          //fprintf(stderr, "env_csdr_fixed_big_bufsize = %d\n", env_csdr_fixed_big_bufsize);
1206  
1207          if(!initialize_buffers()) return -2;
1208          sendbufsize(the_bufsize*factor);
1209          assert(the_bufsize > 0);
1210  
1211          float *taps;
1212          taps=(float*)malloc(taps_length*sizeof(float));
1213          assert(taps);
1214  
1215          firdes_lowpass_f(taps,taps_length,0.5/(float)factor,window);
1216  
1217          int input_skip=0;
1218          int output_size=0;
1219          float* interp_output_buffer = (float*)malloc(sizeof(float)*2*the_bufsize*factor);
1220          for(;;)
1221          {
1222              FEOF_CHECK;
1223              output_size=fir_interpolate_cc((complexf*)input_buffer, (complexf*)interp_output_buffer, the_bufsize, factor, taps, taps_length);
1224              //fprintf(stderr, "os %d\n",output_size);
1225              fwrite(interp_output_buffer, sizeof(complexf), output_size, stdout);
1226              TRY_YIELD;
1227              input_skip=output_size/factor;
1228              memmove((complexf*)input_buffer,((complexf*)input_buffer)+input_skip,(the_bufsize-input_skip)*sizeof(complexf)); //memmove lets the source and destination overlap
1229              fread(((complexf*)input_buffer)+(the_bufsize-input_skip), sizeof(complexf), input_skip, stdin);
1230              //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));
1231          }
1232      }
1233  
1234  
1235  
1236  
1237      /*if(!strcmp(argv[1],"ejw_test"))
1238      {
1239          printf("ejqd=[");
1240          complexf ejw;
1241          float phase=0;
1242          for(int i=0;i<63;i++)
1243          {
1244              e_powj(&ejw,phase);
1245              phase+=PI*0.3;
1246              printf("%g+(%g)*i ",iof(&ejw,0),qof(&ejw,0));
1247          }
1248          printf("];");
1249          return 0;
1250      }*/
1251      if(!strcmp(argv[1],"firdes_lowpass_f"))
1252      {
1253          //Process the params
1254          if(argc<=3) return badsyntax("need required parameters (cutoff_rate, length)");
1255  
1256          float cutoff_rate;
1257          sscanf(argv[2],"%g",&cutoff_rate);
1258  
1259          int length;
1260          sscanf(argv[3],"%d",&length);
1261          if(length%2==0) return badsyntax("number of symmetric FIR filter taps should be odd");
1262  
1263          window_t window = WINDOW_DEFAULT;
1264          if(argc>=5)
1265          {
1266              window=firdes_get_window_from_string(argv[4]);
1267          }
1268          else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); }
1269  
1270          int octave=(argc>=6 && !strcmp("--octave",argv[5]));
1271  
1272          float* taps=(float*)malloc(sizeof(float)*length);
1273  
1274          //Make the filter
1275          firdes_lowpass_f(taps,length,cutoff_rate,window);
1276  
1277          //Do the output
1278          if(octave) printf("taps=[");
1279          for(int i=0;i<length;i++) printf("%g ",taps[i]);
1280          if(octave) printf("];plot(taps);figure(2);freqz(taps);\n");
1281  
1282  
1283          //Wait forever, so that octave won't close just after popping up the window.
1284          //You can close it with ^C.
1285          if(octave) { fflush(stdout); getchar(); }
1286          return 0;
1287      }
1288      if(!strcmp(argv[1],"firdes_bandpass_c"))
1289      {
1290          //Process the params
1291          if(argc<=4) return badsyntax("need required parameters (low_cut, high_cut, length)");
1292  
1293          float low_cut;
1294          sscanf(argv[2],"%g",&low_cut);
1295          float high_cut;
1296          sscanf(argv[3],"%g",&high_cut);
1297  
1298          int length;
1299          sscanf(argv[4],"%d",&length);
1300          if(length%2==0) return badsyntax("number of symmetric FIR filter taps should be odd");
1301  
1302          window_t window = WINDOW_DEFAULT;
1303          if(argc>=6)
1304          {
1305              window=firdes_get_window_from_string(argv[5]);
1306          }
1307          else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window));} 
1308  
1309          int octave=(argc>=7 && !strcmp("--octave",argv[6]));
1310  
1311          complexf* taps=(complexf*)malloc(sizeof(complexf)*length);
1312  
1313          //Make the filter
1314          firdes_bandpass_c(taps, length, low_cut, high_cut, window);
1315  
1316          //Do the output
1317          if(octave) printf("taps=[");
1318          for(int i=0;i<length;i++) printf("(%g)+(%g)*i ",iof(taps,i),qof(taps,i));
1319          int fft_length=1024;
1320          while(fft_length<length) fft_length*=2;
1321          //if(octave) printf("];\n");
1322          if(octave) printf(
1323              "];figure(\"Position\",[0 0 1000 1000]);fser=fft([taps,zeros(1,%d)]);ampl=abs(fser).^2;halfindex=floor(1+size(ampl)(2)/2);\n"
1324              "amplrev=[ampl(halfindex:end),ampl(1:halfindex)];\n" //we have to swap the output of FFT
1325              "subplot(2,1,1);plot(amplrev);\n"
1326              "subplot(2,1,2);plot(arg(fser));\n"
1327              "#figure(2);freqz(taps);\n"
1328              "#figur(3);plot3(taps);\n",fft_length-length);
1329  
1330          //Wait forever, so that octave won't close just after popping up the window.
1331          //You can close it with ^C.
1332          if(octave) { fflush(stdout); getchar(); }
1333          return 0;
1334      }
1335  
1336  #ifdef LIBCSDR_GPL
1337      if(!strcmp(argv[1],"agc_ff"))
1338      {
1339          //Process the params
1340          //Explanation of what these actually do is in the DSP source.
1341          //These good default values are for SSB sampled at 48000 kHz.
1342          short hang_time=200;
1343          if(argc>=3) sscanf(argv[2],"%hd",&hang_time);
1344  
1345          float reference=0.2;
1346          if(argc>=4) sscanf(argv[3],"%g",&reference);
1347  
1348          float attack_rate=0.01;
1349          if(argc>=5) sscanf(argv[4],"%g",&attack_rate);
1350  
1351          float decay_rate=0.0001;
1352          if(argc>=6) sscanf(argv[5],"%g",&decay_rate);
1353  
1354          float max_gain=65536;
1355          if(argc>=7) sscanf(argv[6],"%g",&max_gain);
1356  
1357          short attack_wait=0;
1358          if(argc>=8) sscanf(argv[7],"%hd",&attack_wait);
1359  
1360          float filter_alpha=0.999;//0.001;
1361          if(argc>=9) sscanf(argv[8],"%g",&filter_alpha);
1362  
1363          if(!sendbufsize(initialize_buffers())) return -2;
1364  
1365          float last_gain=1.0;
1366          for(;;)
1367          {
1368              FEOF_CHECK;
1369              FREAD_R;
1370              last_gain=agc_ff(input_buffer, output_buffer, the_bufsize, reference, attack_rate, decay_rate, max_gain, hang_time, attack_wait, filter_alpha, last_gain);
1371              FWRITE_R;
1372              TRY_YIELD;
1373          }
1374      }
1375  #endif
1376  
1377      if(!strcmp(argv[1],"fastagc_ff"))
1378      {
1379  
1380          static fastagc_ff_t input; //is in .bss and gets cleared to zero before main()
1381  
1382          input.input_size=1024;
1383          if(argc>=3) sscanf(argv[2],"%d",&input.input_size);
1384  
1385          getbufsize(); //dummy
1386          sendbufsize(input.input_size);
1387  
1388          input.reference=1.0;
1389          if(argc>=4) sscanf(argv[3],"%g",&input.reference);
1390  
1391          //input.max_peak_ratio=12.0;
1392          //if(argc>=5) sscanf(argv[3],"%g",&input.max_peak_ratio);
1393  
1394          input.buffer_1=(float*)calloc(input.input_size,sizeof(float));
1395          input.buffer_2=(float*)calloc(input.input_size,sizeof(float));
1396          input.buffer_input=(float*)malloc(sizeof(float)*input.input_size);
1397          float* agc_output_buffer=(float*)malloc(sizeof(float)*input.input_size);
1398          for(;;)
1399          {
1400              FEOF_CHECK;
1401              fread(input.buffer_input, sizeof(float), input.input_size, stdin);
1402              fastagc_ff(&input, agc_output_buffer);
1403              fwrite(agc_output_buffer, sizeof(float), input.input_size, stdout);
1404              TRY_YIELD;
1405          }
1406      }
1407  
1408      int suboptimal;
1409      if( (suboptimal=!strcmp(argv[1],"suboptimal_rational_resampler_ff"))||(!strcmp(argv[1],"rational_resampler_ff")) )
1410      {
1411  
1412          //last@2014-11-06: ./docompile; ./csdr yes_f 1.0 | ./csdr suboptimal_rational_resampler_ff 5 2
1413  
1414          //Process the params
1415          if(argc<=3) return badsyntax("need required parameters (interpolation, decimation)");
1416          int interpolation;
1417          sscanf(argv[2],"%d",&interpolation);
1418          int decimation;
1419          sscanf(argv[3],"%d",&decimation);
1420  
1421          float transition_bw=0.05;
1422          if(argc>=5) sscanf(argv[4],"%g",&transition_bw);
1423  
1424          window_t window = WINDOW_DEFAULT;
1425          if(argc>=6)
1426          {
1427              window=firdes_get_window_from_string(argv[5]);
1428          }
1429          else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); }
1430  
1431          if(suboptimal) { errhead(); fprintf(stderr,"note: suboptimal rational resampler chosen.\n"); }
1432  
1433          if(!initialize_buffers()) return -2;
1434  
1435          if(decimation==1&&interpolation==1) { sendbufsize(the_bufsize); clone_(the_bufsize); } //copy input to output in this special case (and stick in this function).
1436  
1437          //Alloc output buffer
1438          int resampler_output_buffer_size=(the_bufsize*interpolation)/decimation;
1439          sendbufsize(resampler_output_buffer_size);
1440          float* resampler_output_buffer=(float*)malloc(sizeof(float)*resampler_output_buffer_size);
1441          float* suboptimal_resampler_temp_buffer = (suboptimal)?(float*)malloc(sizeof(float)*the_bufsize*interpolation):NULL;
1442  
1443          //Generate filter taps
1444          int taps_length = firdes_filter_len(transition_bw);
1445          float* taps = (float*)malloc(sizeof(float)*taps_length);
1446          rational_resampler_get_lowpass_f(taps, taps_length, interpolation, decimation, window);
1447  
1448          static rational_resampler_ff_t d; //in .bss => initialized to zero
1449  
1450          for(;;)
1451          {
1452              FEOF_CHECK;
1453              if(d.input_processed==0) d.input_processed=the_bufsize;
1454              else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed));
1455              fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin);
1456              //if(suboptimal) d=suboptimal_rational_resampler_ff(input_buffer, resampler_output_buffer, the_bufsize, interpolation, decimation, taps, taps_length, suboptimal_resampler_temp_buffer); else
1457              d=rational_resampler_ff(input_buffer, resampler_output_buffer, the_bufsize, interpolation, decimation, taps, taps_length, d.last_taps_delay);
1458              //fprintf(stderr,"resampled %d %d, %d\n",d.output_size, d.input_processed, d.input_processed);
1459              fwrite(resampler_output_buffer, sizeof(float), d.output_size, stdout);
1460              TRY_YIELD;
1461          }
1462      }
1463  
1464  
1465      if(!strcmp(argv[1],"fractional_decimator_ff"))
1466      {
1467          //Process the params
1468          if(argc<=2) return badsyntax("need required parameters (rate)");
1469          float rate;
1470          sscanf(argv[2],"%g",&rate);
1471  
1472          int num_poly_points = 12;
1473          if(argc>=4) sscanf(argv[3],"%d",&num_poly_points);
1474          if(num_poly_points&1) return badsyntax("num_poly_points should be even");
1475          if(num_poly_points<2) return badsyntax("num_poly_points should be >= 2");
1476  
1477          int use_prefilter = 0;
1478          float transition_bw=0.03;
1479          window_t window = WINDOW_DEFAULT;
1480          if(argc>=5)
1481          {
1482              if(!strcmp(argv[4], "--prefilter")) 
1483              {
1484                  errhead(); fprintf(stderr, "using prefilter with default values\n"); 
1485                  use_prefilter = 1;
1486              }
1487              else 
1488              {
1489                  sscanf(argv[4],"%g",&transition_bw);
1490                  if(argc>=6) window = firdes_get_window_from_string(argv[5]);
1491              }
1492          }
1493          errhead(); fprintf(stderr,"use_prefilter = %d, num_poly_points = %d, transition_bw = %g, window = %s\n", 
1494              use_prefilter, num_poly_points, transition_bw, firdes_get_string_from_window(window));
1495  
1496          if(!initialize_buffers()) return -2;
1497          sendbufsize(the_bufsize / rate);
1498  
1499          if(rate==1) clone_(the_bufsize); //copy input to output in this special case (and stick in this function).
1500  
1501          //Generate filter taps
1502          int taps_length = 0;
1503          float* taps = NULL;
1504          if(use_prefilter)
1505          {
1506              taps_length = firdes_filter_len(transition_bw);
1507              errhead(); fprintf(stderr,"taps_length = %d\n",taps_length);
1508              taps = (float*)malloc(sizeof(float)*taps_length);
1509              firdes_lowpass_f(taps, taps_length, 0.5/(rate-transition_bw), window); //0.6 const to compensate rolloff
1510              //for(int=0;i<taps_length; i++) fprintf(stderr,"%g ",taps[i]);
1511          }
1512          else { errhead(); fprintf(stderr,"not using taps\n"); }
1513          fractional_decimator_ff_t d = fractional_decimator_ff_init(rate, num_poly_points, taps, taps_length); 
1514          for(;;)
1515          {
1516              FEOF_CHECK;
1517              if(d.input_processed==0) d.input_processed=the_bufsize;
1518              else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed));
1519              fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin);
1520              fractional_decimator_ff(input_buffer, output_buffer, the_bufsize, &d);
1521              fwrite(output_buffer, sizeof(float), d.output_size, stdout);
1522              //fprintf(stderr, "os = %d, ip = %d\n", d.output_size, d.input_processed);
1523              TRY_YIELD;
1524          }
1525      }
1526  
1527      if(!strcmp(argv[1],"old_fractional_decimator_ff"))
1528      {
1529          //Process the params
1530          if(argc<=2) return badsyntax("need required parameters (rate)");
1531          float rate;
1532          sscanf(argv[2],"%g",&rate);
1533  
1534          float transition_bw=0.03;
1535          if(argc>=4) sscanf(argv[3],"%g",&transition_bw);
1536  
1537          window_t window = WINDOW_DEFAULT;
1538          if(argc>=5)
1539          {
1540              window = firdes_get_window_from_string(argv[4]);
1541          }
1542          else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); }
1543  
1544          if(!initialize_buffers()) return -2;
1545          sendbufsize(the_bufsize / rate);
1546  
1547          if(rate==1) clone_(the_bufsize); //copy input to output in this special case (and stick in this function).
1548  
1549          //Generate filter taps
1550          int taps_length = firdes_filter_len(transition_bw);
1551          errhead(); fprintf(stderr,"taps_length = %d\n",taps_length); 
1552          float* taps = (float*)malloc(sizeof(float)*taps_length);
1553          firdes_lowpass_f(taps, taps_length, 0.59*0.5/(rate-transition_bw), window); //0.6 const to compensate rolloff
1554          //for(int=0;i<taps_length; i++) fprintf(stderr,"%g ",taps[i]);
1555  
1556          static old_fractional_decimator_ff_t d; //in .bss => initialized to zero
1557          for(;;)
1558          {
1559              FEOF_CHECK;
1560              if(d.input_processed==0) d.input_processed=the_bufsize;
1561              else memcpy(input_buffer, input_buffer+d.input_processed, sizeof(float)*(the_bufsize-d.input_processed));
1562              fread(input_buffer+(the_bufsize-d.input_processed), sizeof(float), d.input_processed, stdin);
1563              d = old_fractional_decimator_ff(input_buffer, output_buffer, the_bufsize, rate, taps, taps_length, d);
1564              fwrite(output_buffer, sizeof(float), d.output_size, stdout);
1565              TRY_YIELD;
1566          }
1567      }
1568  
1569      if(!strcmp(argv[1],"fft_cc"))
1570      {
1571          if(argc<=3) return badsyntax("need required parameters (fft_size, out_of_every_n_samples)");
1572          int fft_size;
1573          sscanf(argv[2],"%d",&fft_size);
1574          if(log2n(fft_size)==-1) return badsyntax("fft_size should be power of 2");
1575          int every_n_samples;
1576          sscanf(argv[3],"%d",&every_n_samples);
1577          int benchmark=0;
1578          int octave=0;
1579          window_t window = WINDOW_DEFAULT;
1580          if(argc>=5)
1581          {
1582              window=firdes_get_window_from_string(argv[4]);
1583          }
1584          if(argc>=6)
1585          {
1586              benchmark|=!strcmp("--benchmark",argv[5]);
1587              octave|=!strcmp("--octave",argv[5]);
1588          }
1589          if(argc>=7)
1590          {
1591              benchmark|=!strcmp("--benchmark",argv[6]);
1592              octave|=!strcmp("--octave",argv[6]);
1593          }
1594  
1595          if(!initialize_buffers()) return -2;
1596          sendbufsize(fft_size);
1597  
1598          //make FFT plan
1599          complexf* input=(complexf*)fft_malloc(sizeof(complexf)*fft_size);
1600          complexf* windowed=(complexf*)fft_malloc(sizeof(complexf)*fft_size);
1601          complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_size);
1602          if(benchmark) { errhead(); fprintf(stderr,"benchmarking..."); }
1603          FFT_PLAN_T* plan=make_fft_c2c(fft_size, windowed, output, 1, benchmark);
1604          if(benchmark) fprintf(stderr," done\n");
1605          if(octave) printf("setenv(\"GNUTERM\",\"X11 noraise\");y=zeros(1,%d);semilogy(y,\"ydatasource\",\"y\");\n",fft_size);
1606          float *windowt;
1607          windowt = precalculate_window(fft_size, window);
1608          for(;;)
1609          {
1610              FEOF_CHECK;
1611              if(every_n_samples>fft_size)
1612              {
1613                  fread(input, sizeof(complexf), fft_size, stdin);
1614                  //skipping samples before next FFT (but fseek doesn't work for pipes)
1615                  for(int seek_remain=every_n_samples-fft_size;seek_remain>0;seek_remain-=the_bufsize)
1616                  {
1617                      fread(temp_f, sizeof(complexf), MIN_M(the_bufsize,seek_remain), stdin);
1618                  }
1619              }
1620              else
1621              {
1622                  //overlapped FFT
1623                  for(int i=0;i<fft_size-every_n_samples;i++) input[i]=input[i+every_n_samples];
1624                  fread(input+fft_size-every_n_samples, sizeof(complexf), every_n_samples, stdin);
1625              }
1626              //apply_window_c(input,windowed,fft_size,window);
1627              apply_precalculated_window_c(input,windowed,fft_size,windowt);
1628              fft_execute(plan);
1629              if(octave)
1630              {
1631                  printf("fftdata=[");
1632                  //we have to swap the two parts of the array to get a valid spectrum
1633                  for(int i=fft_size/2;i<fft_size;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i));
1634                  for(int i=0;i<fft_size/2;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i));
1635                  printf(
1636                      "];\n"
1637                      "y=abs(fftdata);\n"
1638                      "refreshdata;\n"
1639                  );
1640              }
1641              else fwrite(output, sizeof(complexf), fft_size, stdout);
1642              TRY_YIELD;
1643          }
1644      }
1645      #define LOGPOWERCF_BUFSIZE 64
1646      if(!strcmp(argv[1],"logpower_cf"))
1647      {
1648          float add_db=0;
1649          if(argc>=3) sscanf(argv[2],"%g",&add_db);
1650  
1651          if(!sendbufsize(initialize_buffers())) return -2;
1652  
1653          for(;;)
1654          {
1655              FEOF_CHECK;
1656              fread(input_buffer, sizeof(complexf), the_bufsize, stdin);
1657              logpower_cf((complexf*)input_buffer,output_buffer, the_bufsize, add_db);
1658              fwrite(output_buffer, sizeof(float), the_bufsize, stdout);
1659              TRY_YIELD;
1660          }
1661      }
1662  
1663      if(!strcmp(argv[1],"logaveragepower_cf"))
1664      {
1665          bigbufs=1;
1666          if(argc<=4) return badsyntax("need required parameters (add_db, fft_size, avgnumber)"); 
1667          float add_db=0;
1668          int avgnumber=0;
1669          int fft_size=0;
1670          
1671          sscanf(argv[2],"%g",&add_db);
1672          sscanf(argv[3],"%d",&fft_size);
1673          sscanf(argv[4],"%d",&avgnumber);
1674          
1675          float *input = malloc(sizeof(float)*2 * fft_size);
1676          float *output = malloc(sizeof(float) * fft_size);
1677  
1678          add_db -= 10.0*log10(avgnumber);
1679          for(;;)
1680          {
1681              int i,n;
1682              for(i = 0; i < fft_size; i++) {
1683                  output[i] = 0;
1684              }
1685              FEOF_CHECK;
1686              for(n = 0; n < avgnumber; n++) {
1687                  fread (input, sizeof(float)*2, fft_size, stdin);
1688                  accumulate_power_cf((complexf*)input, output, fft_size);
1689              }
1690              log_ff(output, output, fft_size, add_db);
1691              fwrite (output, sizeof(float), fft_size, stdout);
1692              TRY_YIELD;
1693          }
1694          return 0;
1695      }
1696  
1697      if(!strcmp(argv[1],"fft_exchange_sides_ff"))
1698      {
1699          if(argc<=2) return badsyntax("need required parameters (fft_size)");
1700          int fft_size;
1701          sscanf(argv[2],"%d",&fft_size);
1702          if(!getbufsize()) return -2; //dummy
1703          sendbufsize(fft_size);
1704          float* input_buffer_s1 = (float*)malloc(sizeof(float)*fft_size/2);
1705          float* input_buffer_s2 = (float*)malloc(sizeof(float)*fft_size/2);
1706          for(;;)
1707          {
1708              FEOF_CHECK;
1709              fread(input_buffer_s1, sizeof(float), fft_size/2, stdin);
1710              fread(input_buffer_s2, sizeof(float), fft_size/2, stdin);
1711              fwrite(input_buffer_s2, sizeof(float), fft_size/2, stdout);
1712              fwrite(input_buffer_s1, sizeof(float), fft_size/2, stdout);
1713              TRY_YIELD;
1714          }
1715      }
1716  
1717      if(!strcmp(argv[1],"fft_one_side_ff"))
1718      {
1719          if(argc<=2) return badsyntax("need required parameters (fft_size)");
1720          int fft_size;
1721          sscanf(argv[2],"%d",&fft_size);
1722          if(!getbufsize()) return -2; 
1723          sendbufsize(fft_size);
1724          float* input_buffer_s1 = (float*)malloc(sizeof(float)*fft_size/2);
1725          float* input_buffer_s2 = (float*)malloc(sizeof(float)*fft_size/2);
1726          for(;;)
1727          {
1728              FEOF_CHECK;
1729              fread(input_buffer_s1, sizeof(float), fft_size/2, stdin);
1730              fread(input_buffer_s2, sizeof(float), fft_size/2, stdin);
1731              fwrite(input_buffer_s1, sizeof(float), fft_size/2, stdout);
1732              TRY_YIELD;
1733          }
1734      }
1735  
1736  
1737  #ifdef USE_IMA_ADPCM
1738  
1739  #define COMPRESS_FFT_PAD_N 10
1740  //We will pad the FFT at the beginning, with the first value of the input data, COMPRESS_FFT_PAD_N times.
1741  //No, this is not advanced DSP, just the ADPCM codec produces some gabarge samples at the beginning,
1742  //so we just add data to become garbage and get skipped.
1743  //COMPRESS_FFT_PAD_N should be even.
1744  
1745      if(!strcmp(argv[1],"compress_fft_adpcm_f_u8"))
1746      {
1747          if(argc<=2) return badsyntax("need required parameters (fft_size)");
1748          int fft_size;
1749          sscanf(argv[2],"%d",&fft_size);
1750          int real_data_size=fft_size+COMPRESS_FFT_PAD_N;
1751          if(!getbufsize()) return -2; //dummy
1752          sendbufsize(real_data_size);
1753          float* input_buffer_cwa = (float*)malloc(sizeof(float)*real_data_size);
1754          short* temp_buffer_cwa = (short*)malloc(sizeof(short)*real_data_size);
1755          unsigned char* output_buffer_cwa = (unsigned char*)malloc(sizeof(unsigned char)*(real_data_size/2));
1756          ima_adpcm_state_t d;
1757          d.index=d.previousValue=0;
1758          for(;;)
1759          {
1760              FEOF_CHECK;
1761              fread(input_buffer_cwa+COMPRESS_FFT_PAD_N, sizeof(float), fft_size, stdin);
1762              for(int i=0;i<COMPRESS_FFT_PAD_N;i++) input_buffer_cwa[i]=input_buffer_cwa[COMPRESS_FFT_PAD_N]; //do padding
1763              for(int i=0;i<real_data_size;i++) temp_buffer_cwa[i]=input_buffer_cwa[i]*100; //convert float dB values to short
1764              encode_ima_adpcm_i16_u8(temp_buffer_cwa, output_buffer_cwa, real_data_size, d); //we always return to original d at any new buffer
1765              fwrite(output_buffer_cwa, sizeof(unsigned char), real_data_size/2, stdout);
1766              TRY_YIELD;
1767          }
1768      }
1769  #endif
1770  
1771      if(!strcmp(argv[1],"fft_benchmark"))
1772      {
1773          if(argc<=3) return badsyntax("need required parameters (fft_size, fft_cycles)");
1774          int fft_size;
1775          sscanf(argv[2],"%d",&fft_size);
1776          int fft_cycles;
1777          sscanf(argv[3],"%d",&fft_cycles);
1778  
1779          int benchmark=(argc>=5)&&!strcmp(argv[4],"--benchmark");
1780          errhead(); fprintf(stderr,"FFT library used: %s\n",FFT_LIBRARY_USED);
1781  
1782          complexf* input=(complexf*)fft_malloc(sizeof(complexf)*fft_size);
1783          complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_size);
1784  
1785          //fill input with random data
1786          srand(time(NULL));
1787          for(int i=0;i<fft_size;i++)
1788          {
1789              iof(input,i)=rand()/(float)INT_MAX;
1790              qof(input,i)=rand()/(float)INT_MAX;
1791          }
1792  
1793          //initialize FFT library, and measure time
1794          errhead(); fprintf(stderr,"initializing... ");
1795          struct timespec start_time, end_time;
1796          clock_gettime(CLOCK_MONOTONIC_RAW, &start_time);
1797          FFT_PLAN_T* plan=make_fft_c2c(fft_size,input,output,1,benchmark);
1798          clock_gettime(CLOCK_MONOTONIC_RAW, &end_time);
1799          fprintf(stderr,"done in %g seconds.\n",TIME_TAKEN(start_time,end_time));
1800  
1801          //do the actual measurement about the FFT
1802          clock_gettime(CLOCK_MONOTONIC_RAW, &start_time);
1803          for(int i=0;i<fft_cycles;i++) fft_execute(plan);
1804          clock_gettime(CLOCK_MONOTONIC_RAW, &end_time);
1805          float time_taken_fft = TIME_TAKEN(start_time,end_time);
1806          errhead(); fprintf(stderr,"%d transforms of %d processed in %g seconds, %g seconds each.\n",fft_cycles,fft_size,time_taken_fft,time_taken_fft/fft_cycles);
1807          return 0;
1808      }
1809  
1810      if(!strcmp(argv[1],"bandpass_fir_fft_cc")) //this command does not exist as a separate function
1811      {
1812          float low_cut;
1813          float high_cut;
1814          float transition_bw;
1815          window_t window = WINDOW_DEFAULT;
1816          int fd;
1817          if(fd=init_fifo(argc,argv))
1818          {
1819              while(!read_fifo_ctl(fd,"%g %g\n",&low_cut,&high_cut)) usleep(10000);
1820              if(argc<=4) return badsyntax("need more required parameters (transition_bw)");
1821          }
1822          else
1823          {
1824              if(argc<=4) return badsyntax("need required parameters (low_cut, high_cut, transition_bw)");
1825              sscanf(argv[2],"%g",&low_cut);
1826              sscanf(argv[3],"%g",&high_cut);
1827          }
1828          sscanf(argv[4],"%g",&transition_bw);
1829          if(argc>=6) window=firdes_get_window_from_string(argv[5]);
1830          else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); }
1831  
1832          //calculate the FFT size and the other length parameters
1833          int taps_length=firdes_filter_len(transition_bw); //the number of non-zero taps
1834          int fft_size=next_pow2(taps_length); //we will have to pad the taps with zeros until the next power of 2 for FFT
1835          //the number of padding zeros is the number of output samples we will be able to take away after every processing step, and it looks sane to check if it is large enough.
1836          if (fft_size-taps_length<200) fft_size<<=1;
1837          int input_size = fft_size - taps_length + 1;
1838          int overlap_length = taps_length - 1;
1839          errhead(); fprintf(stderr,"(fft_size = %d) = (taps_length = %d) + (input_size = %d) - 1\n(overlap_length = %d) = taps_length - 1\n", fft_size, taps_length, input_size, overlap_length );
1840          if (fft_size<=2) return badsyntax("FFT size error.");
1841  
1842          if(!sendbufsize(getbufsize())) return -2;
1843  
1844          //prepare making the filter and doing FFT on it
1845          complexf* taps=(complexf*)calloc(sizeof(complexf),fft_size); //initialize to zero
1846          complexf* taps_fft=(complexf*)malloc(sizeof(complexf)*fft_size);
1847          FFT_PLAN_T* plan_taps = make_fft_c2c(fft_size, taps, taps_fft, 1, 0); //forward, don't benchmark (we need this only once)
1848  
1849          //make FFT plans for continously processing the input
1850          complexf* input = fft_malloc(fft_size*sizeof(complexf));
1851          complexf* input_fourier = fft_malloc(fft_size*sizeof(complexf));
1852          FFT_PLAN_T* plan_forward = make_fft_c2c(fft_size, input, input_fourier, 1, 1); //forward, do benchmark
1853  
1854          complexf* output_fourier = fft_malloc(fft_size*sizeof(complexf));
1855          complexf* output_1 = fft_malloc(fft_size*sizeof(complexf));
1856          complexf* output_2 = fft_malloc(fft_size*sizeof(complexf));
1857          //we create 2x output buffers so that one will preserve the previous overlap:
1858          FFT_PLAN_T* plan_inverse_1 = make_fft_c2c(fft_size, output_fourier, output_1, 0, 1); //inverse, do benchmark
1859          FFT_PLAN_T* plan_inverse_2 = make_fft_c2c(fft_size, output_fourier, output_2, 0, 1);
1860          //we initialize this buffer to 0 as it will be taken as the overlap source for the first time:
1861          for(int i=0;i<fft_size;i++) iof(plan_inverse_2->output,i)=qof(plan_inverse_2->output,i)=0;
1862  
1863          for(int i=input_size;i<fft_size;i++) iof(input,i)=qof(input,i)=0; //we pre-pad the input buffer with zeros
1864  
1865          for(;;)
1866          {
1867              //make the filter
1868              errhead(); fprintf(stderr,"filter initialized, low_cut = %g, high_cut = %g\n",low_cut,high_cut);
1869              firdes_bandpass_c(taps, taps_length, low_cut, high_cut, window);
1870              fft_execute(plan_taps);
1871  
1872              for(int odd=0;;odd=!odd) //the processing loop
1873              {
1874                  FEOF_CHECK;
1875                  fread(input, sizeof(complexf), input_size, stdin);
1876                  FFT_PLAN_T* plan_inverse = (odd)?plan_inverse_2:plan_inverse_1;
1877                  FFT_PLAN_T* plan_contains_last_overlap = (odd)?plan_inverse_1:plan_inverse_2; //the other
1878                  complexf* last_overlap = (complexf*)plan_contains_last_overlap->output + input_size; //+ fft_size - overlap_length;
1879                  apply_fir_fft_cc (plan_forward, plan_inverse, taps_fft, last_overlap, overlap_length);
1880                  int returned=fwrite(plan_inverse->output, sizeof(complexf), input_size, stdout);
1881                  if(read_fifo_ctl(fd,"%g %g\n",&low_cut,&high_cut)) break;
1882                  TRY_YIELD;
1883              }
1884          }
1885  
1886      }
1887  
1888  #ifdef USE_IMA_ADPCM
1889  #define IMA_ADPCM_BUFSIZE BUFSIZE
1890  
1891      if( (!strcmp(argv[1],"encode_ima_adpcm_i16_u8"))||(!strcmp(argv[1],"encode_ima_adpcm_s16_u8")) )
1892      {
1893          if(!sendbufsize(initialize_buffers()/2)) return -2;
1894          ima_adpcm_state_t d;
1895          d.index=d.previousValue=0;
1896          for(;;)
1897          {
1898              FEOF_CHECK;
1899              fread(buffer_i16, sizeof(short), the_bufsize, stdin);
1900              d=encode_ima_adpcm_i16_u8(buffer_i16, buffer_u8, the_bufsize, d);
1901              fwrite(buffer_u8, sizeof(unsigned char), the_bufsize/2, stdout);
1902              TRY_YIELD;
1903          }
1904      }
1905  
1906      if( (!strcmp(argv[1],"decode_ima_adpcm_u8_i16"))||(!strcmp(argv[1],"decode_ima_adpcm_u8_s16")) )
1907      {
1908          ima_adpcm_state_t d;
1909          d.index=d.previousValue=0;
1910          if(!sendbufsize(initialize_buffers()*2)) return -2;
1911          for(;;)
1912          {
1913              FEOF_CHECK;
1914              fread(buffer_u8, sizeof(unsigned char), the_bufsize, stdin);
1915              d=decode_ima_adpcm_u8_i16(buffer_u8, buffer_i16, the_bufsize, d);
1916              fwrite(buffer_i16, sizeof(short), the_bufsize*2, stdout);
1917              TRY_YIELD;
1918          }
1919      }
1920  #endif
1921  
1922      if(!strcmp(argv[1],"flowcontrol"))
1923      {
1924          if(argc<=3) return badsyntax("need required parameters (data_rate, reads_per_seconds)");
1925          int data_rate;
1926          sscanf(argv[2],"%d",&data_rate);
1927          int reads_per_second;
1928          sscanf(argv[3],"%d",&reads_per_second);
1929          int flowcontrol_bufsize=ceil(1.*(double)data_rate/reads_per_second);
1930          if(!getbufsize()) return -2;
1931          sendbufsize(flowcontrol_bufsize);
1932          unsigned char* flowcontrol_buffer = (unsigned char*)malloc(sizeof(unsigned char)*flowcontrol_bufsize);
1933          int flowcontrol_sleep=floor(1000000./reads_per_second);
1934          errhead(); fprintf(stderr, "flowcontrol_bufsize = %d, flowcontrol_sleep = %d\n", flowcontrol_bufsize, flowcontrol_sleep);
1935          for(;;)
1936          {
1937              FEOF_CHECK;
1938              fread(flowcontrol_buffer, sizeof(unsigned char), flowcontrol_bufsize, stdin);
1939              fwrite(flowcontrol_buffer, sizeof(unsigned char), flowcontrol_bufsize, stdout);
1940              usleep(flowcontrol_sleep);
1941              TRY_YIELD;
1942          }
1943      }
1944  
1945  #if 0
1946      if(!strcmp(argv[1],"flowcontrol"))
1947      {
1948          if(argc<=3) return badsyntax("need required parameters (data_rate, reads_per_seconds)");
1949  
1950          int data_rate;
1951          sscanf(argv[2],"%d",&data_rate);
1952  
1953          int reads_per_second=0;
1954          if(strcmp(argv[3],"auto")) sscanf(argv[3],"%d",&reads_per_second);
1955  
1956          float prebuffer=2;
1957          if(argc>4) sscanf(argv[4],"%g",&prebuffer);
1958  
1959          int thrust=10;
1960          if(argc>5) sscanf(argv[5],"%d",&thrust);
1961  
1962          int flowcontrol_readsize, flowcontrol_bufsize, got_bufsize;
1963  
1964          if(!(got_bufsize=getbufsize())) return -2;
1965  
1966          if(reads_per_second)
1967          {
1968              flowcontrol_readsize=ceil(1.*(double)data_rate/reads_per_second);
1969          }
1970          else
1971          {
1972              flowcontrol_readsize=got_bufsize;
1973              reads_per_second=data_rate/flowcontrol_readsize;
1974          }
1975          flowcontrol_bufsize=flowcontrol_readsize*floor(reads_per_second*prebuffer);
1976  
1977          int flowcontrol_bufindex=0;
1978          unsigned char* flowcontrol_buffer = (unsigned char*)malloc(sizeof(unsigned char)*flowcontrol_bufsize);
1979          int flowcontrol_sleep=floor(1000000./reads_per_second);
1980  
1981          fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK);
1982  
1983          sendbufsize(flowcontrol_readsize);
1984          fflush(stdout);
1985  
1986          int flowcontrol_is_buffering = 1;
1987          int read_return;
1988  
1989          struct timespec start_time, end_time;
1990  
1991          unsigned long long int all_bytes_written=0;
1992          int test=0;
1993  
1994          fprintf(stderr, "flowcontrol: flowcontrol_readsize = %d, flowcontrol_bufsize = %d, flowcontrol_sleep = %d\n", flowcontrol_readsize, flowcontrol_bufsize, flowcontrol_sleep);
1995          for (; ;) //my friend has told me that this is like two smileys ;)
1996          {
1997              FEOF_CHECK;
1998              fprintf(stderr, "r");
1999              read_return=read(STDIN_FILENO, flowcontrol_buffer+flowcontrol_bufindex, sizeof(unsigned char) * (flowcontrol_bufsize-flowcontrol_bufindex) );
2000              fprintf(stderr, "t");
2001              if(read_return>0) flowcontrol_bufindex+=read_return;
2002  
2003  
2004              if(flowcontrol_is_buffering)
2005              {
2006                  fprintf(stderr, "flowcontrol: buffering, flowcontrol_bufindex = %d\n", flowcontrol_bufindex);
2007                  if(flowcontrol_bufindex==flowcontrol_bufsize) { flowcontrol_is_buffering = 0; clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); }
2008                  else if(read_return<=0) continue;
2009              }
2010              else {
2011                  clock_gettime(CLOCK_MONOTONIC_RAW, &end_time);
2012                  int thrust_added=0;
2013                  while( (all_bytes_written+thrust*flowcontrol_readsize) / TIME_TAKEN(start_time,end_time) < data_rate )
2014                  {
2015                      thrust_added |= thrust++;
2016                  }
2017                  //if(!(test++%10)) fprintf(stderr, "abw=%g\n", all_bytes_written / TIME_TAKEN(start_time,end_time));
2018                  /*if(!thrust_added && TIME_TAKEN(start_time,end_time)>50)
2019                  {
2020                      clock_gettime(CLOCK_MONOTONIC_RAW, &start_time);
2021                      all_bytes_written=0;
2022                  }*/
2023                  while(all_bytes_written>data_rate && TIME_TAKEN(start_time,end_time)>1)
2024                  {
2025                      all_bytes_written-=data_rate;
2026                      start_time.tv_sec++;
2027                  }
2028                  do
2029                  {
2030                      //if(thrust) fprintf(stderr, "flowcontrol: %d .. thrust\n", thrust);
2031                      write(STDOUT_FILENO, flowcontrol_buffer, flowcontrol_readsize);
2032                      fflush(stdout);
2033                      //fsync(STDOUT_FILENO);
2034                      memmove(flowcontrol_buffer, flowcontrol_buffer+flowcontrol_readsize, flowcontrol_bufindex-flowcontrol_readsize);
2035                      flowcontrol_bufindex -= flowcontrol_readsize;
2036                      all_bytes_written += flowcontrol_readsize;
2037                  } while(thrust && thrust-- && flowcontrol_bufindex>=flowcontrol_readsize);
2038              }
2039  
2040              usleep(flowcontrol_sleep);
2041              TRY_YIELD;
2042          }
2043      }
2044  #endif
2045  
2046      if(!strcmp(argv[1],"through"))
2047      {
2048          struct timespec start_time, end_time;
2049          if(!sendbufsize(initialize_buffers())) return -2;
2050  
2051          int time_now_sec=0;
2052          int buffer_count=0;
2053  
2054          unsigned char* through_buffer;
2055          through_buffer = (unsigned char*)malloc(the_bufsize*sizeof(float));
2056  
2057  
2058          for(;;)
2059          {
2060              FEOF_CHECK;
2061              fread(through_buffer, sizeof(float), the_bufsize, stdin);
2062  
2063              if(!time_now_sec)
2064              {
2065                  time_now_sec=1;
2066                  clock_gettime(CLOCK_MONOTONIC_RAW, &start_time);
2067              }
2068              else
2069              {
2070                  clock_gettime(CLOCK_MONOTONIC_RAW, &end_time);
2071                  float timetaken;
2072                  if(time_now_sec<(timetaken=TIME_TAKEN(start_time,end_time)))
2073                  {
2074                      fprintf( stderr, "through: %lu bytes/s, buffer #%d\n", (unsigned long)floor((float)buffer_count*the_bufsize*sizeof(float)/timetaken), buffer_count );
2075                      time_now_sec=ceil(timetaken);
2076                  }
2077              }
2078              fwrite(through_buffer, sizeof(float), the_bufsize, stdout);
2079              buffer_count++;
2080              TRY_YIELD;
2081          }
2082      }
2083  
2084      if(!strcmp(argv[1],"dsb_fc"))
2085      {
2086          float q_value = 0;
2087          if(argc>=3) sscanf(argv[2],"%g",&q_value);
2088  
2089          if(!sendbufsize(initialize_buffers())) return -2;
2090          for(;;)
2091          {
2092              FEOF_CHECK;
2093              FREAD_R;
2094              for(int i=0;i<the_bufsize;i++)
2095              {
2096                  iof(output_buffer,i)=input_buffer[i];
2097                  qof(output_buffer,i)=q_value;
2098              }
2099              FWRITE_C;
2100              TRY_YIELD;
2101          }
2102      }
2103  
2104      if(!strcmp(argv[1],"convert_f_samplerf"))
2105      {
2106          if(argc<=2) return badsyntax("need required parameter (wait_for_this_sample)");
2107  
2108          unsigned wait_for_this_sample;
2109          sscanf(argv[2],"%u",&wait_for_this_sample);
2110  
2111          if(!sendbufsize(initialize_buffers())) return -2;
2112          unsigned char* samplerf_buf = (unsigned char*) malloc(16*the_bufsize);
2113          for(;;)
2114          {
2115              FEOF_CHECK;
2116              FREAD_R;
2117              for(int i=0;i<the_bufsize;i++)
2118              {
2119                  *((double*)(&samplerf_buf[16*i])) = input_buffer[i];
2120                  *((unsigned*)(&samplerf_buf[16*i+8])) = wait_for_this_sample;
2121                  *((unsigned*)(&samplerf_buf[16*i+12])) = 0;
2122  
2123              }
2124              fwrite(samplerf_buf, 16, the_bufsize, stdout);
2125              TRY_YIELD;
2126          }
2127      }
2128  
2129      if(!strcmp(argv[1],"add_dcoffset_cc"))
2130      {
2131          if(!sendbufsize(initialize_buffers())) return -2;
2132          for(;;)
2133          {
2134              FEOF_CHECK;
2135              FREAD_C;
2136              add_dcoffset_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize);
2137              FWRITE_C;
2138              TRY_YIELD;
2139          }
2140      }
2141  
2142      if(!strcmp(argv[1],"fmmod_fc"))
2143      {
2144          if(!sendbufsize(initialize_buffers())) return -2;
2145          float last_phase = 0;
2146          for(;;)
2147          {
2148              FEOF_CHECK;
2149              FREAD_R;
2150              last_phase = fmmod_fc(input_buffer, (complexf*)output_buffer, the_bufsize, last_phase);
2151              FWRITE_C;
2152              TRY_YIELD;
2153          }
2154      }
2155  
2156      if(!strcmp(argv[1],"fixed_amplitude_cc"))
2157      {
2158          if(argc<=2) return badsyntax("need required parameter (new_amplitude)");
2159  
2160          float new_amplitude;
2161          sscanf(argv[2],"%g",&new_amplitude);
2162  
2163          if(!sendbufsize(initialize_buffers())) return -2;
2164          for(;;)
2165          {
2166              FEOF_CHECK;
2167              FREAD_C;
2168              fixed_amplitude_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, new_amplitude);
2169              FWRITE_C;
2170              TRY_YIELD;
2171          }
2172      }
2173  
2174      if((!strcmp(argv[1],"mono2stereo_i16"))||(!strcmp(argv[1],"mono2stereo_s16")))
2175      {
2176          if(!sendbufsize(initialize_buffers())) return -2;
2177          float last_phase = 0;
2178          for(;;)
2179          {
2180              FEOF_CHECK;
2181              fread (input_buffer, sizeof(short), the_bufsize, stdin);
2182              for(int i=0;i<the_bufsize;i++)
2183              {
2184                  *(((short*)output_buffer)+2*i)=*(((short*)input_buffer)+i);
2185                  *(((short*)output_buffer)+2*i+1)=*(((short*)input_buffer)+i);
2186              }
2187              fwrite (output_buffer, sizeof(short)*2, the_bufsize, stdout);
2188              TRY_YIELD;
2189          }
2190      }
2191  
2192      if(!strcmp(argv[1],"squelch_and_smeter_cc"))
2193      {
2194          if(!sendbufsize(initialize_buffers())) return -2;
2195          float power;
2196          float squelch_level;
2197          int decimation;
2198          int report_every_nth;
2199          int fd;
2200          char power_value_buf[101];
2201          int power_value_buf_size;
2202          int report_cntr=0;
2203          complexf* zerobuf = (complexf*)malloc(sizeof(complexf)*the_bufsize);
2204          for(int i=0;i<the_bufsize*2;i++) *(((float*)zerobuf)+i)=0;
2205          if(fd=init_fifo(argc,argv)) while(!read_fifo_ctl(fd,"%g\n",&squelch_level)) usleep(10000);
2206          else return badsyntax("need required parameter (--fifo <fifo>)");
2207          errhead(); fprintf(stderr, "initial squelch level is %g\n", squelch_level);
2208          if((argc<=5)||((argc>5)&&(strcmp(argv[4],"--outfifo")))) return badsyntax("need required parameter (--outfifo <fifo>)");
2209          int fd2 = open(argv[5], O_WRONLY);
2210          if(fd2==-1) return badsyntax("error while opening --outfifo");
2211          int flags = fcntl(fd2, F_GETFL, 0);
2212          fcntl(fd2, F_SETFL, flags | O_NONBLOCK);
2213          if(argc<=6) return badsyntax("need required parameter (use_every_nth)");
2214          sscanf(argv[6],"%d",&decimation);
2215          if(decimation<=0) return badsyntax("use_every_nth <= 0 is invalid");
2216          if(argc<=7) return badsyntax("need required parameter (report_every_nth)");
2217          sscanf(argv[7],"%d",&report_every_nth);
2218          if(report_every_nth<=0) return badsyntax("report_every_nth <= 0 is invalid");
2219          for(;;)
2220          {
2221              FEOF_CHECK;
2222              FREAD_C; //read input data
2223              power = get_power_c((complexf*)input_buffer, the_bufsize, decimation);
2224              if(report_cntr++>report_every_nth)
2225              {
2226                  report_cntr=0;
2227                  power_value_buf_size=snprintf(power_value_buf,100,"%g\n",power);
2228                  write(fd2,power_value_buf,power_value_buf_size*sizeof(char));
2229            }
2230              if(squelch_level==0||power>=squelch_level)
2231              {
2232                  //fprintf(stderr,"P");
2233                  fwrite(input_buffer, sizeof(complexf), the_bufsize, stdout);
2234              }
2235              else
2236              {
2237                  //fprintf(stderr,"S");
2238                  fwrite(zerobuf, sizeof(complexf), the_bufsize, stdout);
2239              }
2240              if(read_fifo_ctl(fd,"%g\n",&squelch_level)) { errhead(); fprintf(stderr, "new squelch level is %g\n", squelch_level); }
2241              TRY_YIELD;
2242          }
2243      }
2244  
2245      /*
2246        ______        _   _____  _____   _____ 
2247       |  ____|      | | |  __ \|  __ \ / ____|
2248       | |__ __ _ ___| |_| |  | | |  | | |     
2249       |  __/ _` / __| __| |  | | |  | | |     
2250       | | | (_| \__ \ |_| |__| | |__| | |____ 
2251       |_|  \__,_|___/\__|_____/|_____/ \_____|
2252  
2253      */                                         
2254                                           
2255      if( !strcmp(argv[1],"fastddc_fwd_cc") ) //<decimation> [transition_bw [window]]
2256      {   
2257          
2258          int decimation;
2259          if(argc<=2) return badsyntax("need required parameter (decimation)");
2260          sscanf(argv[2],"%d",&decimation);
2261          
2262          float transition_bw = 0.05;
2263          if(argc>3) sscanf(argv[3],"%g",&transition_bw);
2264  
2265          window_t window = WINDOW_DEFAULT;
2266          if(argc>4)  window=firdes_get_window_from_string(argv[4]);
2267          else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); }
2268  
2269          fastddc_t ddc; 
2270          if(fastddc_init(&ddc, transition_bw, decimation, 0)) { badsyntax("error in fastddc_init()"); return 1; }
2271          fastddc_print(&ddc,"fastddc_fwd_cc");
2272  
2273          if(!initialize_buffers()) return -2;
2274          sendbufsize(ddc.fft_size);
2275  
2276          //make FFT plan
2277          complexf* input =    (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size);
2278          complexf* windowed = (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size);
2279          complexf* output =   (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size);
2280  
2281          for(int i=0;i<ddc.fft_size;i++) iof(input,i)=qof(input,i)=0; //null the input buffer
2282  
2283          int benchmark = 1; 
2284          if(benchmark) { errhead(); fprintf(stderr,"benchmarking FFT..."); }
2285          FFT_PLAN_T* plan=make_fft_c2c(ddc.fft_size, windowed, output, 1, benchmark);
2286          if(benchmark) fprintf(stderr," done\n");
2287  
2288          for(;;)
2289          {
2290              FEOF_CHECK;
2291              //overlapped FFT
2292              for(int i=0;i<ddc.overlap_length;i++) input[i]=input[i+ddc.input_size];
2293              fread(input+ddc.overlap_length, sizeof(complexf), ddc.input_size, stdin);
2294              //apply_window_c(input,windowed,ddc.fft_size,window);
2295              memcpy(windowed, input, ddc.fft_size*sizeof(complexf)); //we can switch off windows; TODO: it is likely that we shouldn't apply a window to both the FFT and the filter.
2296              fft_execute(plan);
2297              fwrite(output, sizeof(complexf), ddc.fft_size, stdout);
2298              TRY_YIELD;
2299          }
2300      }
2301  
2302      if( !strcmp(argv[1],"fastddc_inv_cc") ) //<shift_rate> <decimation> [transition_bw [window]]
2303      {   
2304          float shift_rate;
2305          int plusarg=0;
2306  
2307          int fd;
2308          if(fd=init_fifo(argc,argv))
2309          {
2310              while(!read_fifo_ctl(fd,"%g\n",&shift_rate)) usleep(10000);
2311              plusarg=1;
2312          }
2313          else
2314          {
2315              if(argc<=2) return badsyntax("need required parameter (rate)"); 
2316              sscanf(argv[2],"%g",&shift_rate);
2317          }
2318  
2319          int decimation;
2320          if(argc<=3+plusarg) return badsyntax("need required parameter (decimation)");
2321          sscanf(argv[3+plusarg],"%d",&decimation);
2322          //fprintf(stderr, "dec=%d %d\n", decimation);
2323  
2324          float transition_bw = 0.05;
2325          if(argc>4+plusarg) sscanf(argv[4+plusarg],"%g",&transition_bw);
2326  
2327          window_t window = WINDOW_DEFAULT;
2328          if(argc>5+plusarg)  window=firdes_get_window_from_string(argv[5+plusarg]);
2329          else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); }
2330  
2331          for(;;)
2332          {
2333  
2334          fastddc_t ddc; 
2335          if(fastddc_init(&ddc, transition_bw, decimation, shift_rate)) { badsyntax("error in fastddc_init()"); return 1; }
2336          fastddc_print(&ddc,"fastddc_inv_cc");
2337  
2338          if(!initialize_buffers()) return -2;
2339          sendbufsize(ddc.post_input_size/ddc.post_decimation); //TODO not exactly correct
2340  
2341          //prepare making the filter and doing FFT on it
2342          complexf* taps=(complexf*)calloc(sizeof(complexf),ddc.fft_size); //initialize to zero
2343          complexf* taps_fft=(complexf*)malloc(sizeof(complexf)*ddc.fft_size);
2344          FFT_PLAN_T* plan_taps = make_fft_c2c(ddc.fft_size, taps, taps_fft, 1, 0); //forward, don't benchmark (we need this only once)
2345  
2346          //make the filter
2347          float filter_half_bw = 0.5/decimation;
2348          errhead(); fprintf(stderr, "preparing a bandpass filter of [%g, %g] cutoff rates. Real transition bandwidth is: %g\n", (-shift_rate)-filter_half_bw, (-shift_rate)+filter_half_bw, 4.0/ddc.taps_length);
2349          firdes_bandpass_c(taps, ddc.taps_length, (-shift_rate)-filter_half_bw, (-shift_rate)+filter_half_bw, window);
2350          fft_execute(plan_taps);
2351          fft_swap_sides(taps_fft,ddc.fft_size);
2352  
2353          //make FFT plan
2354          complexf* inv_input =    (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_inv_size);
2355          complexf* inv_output =   (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_inv_size);
2356          errhead(); fprintf(stderr,"benchmarking FFT...");
2357          FFT_PLAN_T* plan_inverse = make_fft_c2c(ddc.fft_inv_size, inv_input, inv_output, 0, 1); //inverse, do benchmark
2358          fprintf(stderr," done\n");
2359          
2360          //alloc. buffers
2361          complexf* input =    (complexf*)fft_malloc(sizeof(complexf)*ddc.fft_size);
2362          complexf* output =   (complexf*)fft_malloc(sizeof(complexf)*ddc.post_input_size);
2363  
2364          decimating_shift_addition_status_t shift_stat;
2365          bzero(&shift_stat, sizeof(shift_stat));
2366          for(;;)
2367          {
2368              FEOF_CHECK;
2369              fread(input, sizeof(complexf), ddc.fft_size, stdin);
2370              shift_stat = fastddc_inv_cc(input, output, &ddc, plan_inverse, taps_fft, shift_stat);
2371              fwrite(output, sizeof(complexf), shift_stat.output_size, stdout);
2372              //fprintf(stderr, "ss os = %d\n", shift_stat.output_size);
2373              TRY_YIELD;
2374              if(read_fifo_ctl(fd,"%g\n",&shift_rate)) break;
2375          }
2376  
2377          }
2378      }
2379  
2380      if( !strcmp(argv[1], "_fft2octave") ) 
2381      {
2382          int fft_size;
2383          if(argc<=2) return badsyntax("need required parameter (fft_size)");
2384          sscanf(argv[2],"%d",&fft_size);
2385  
2386          complexf* fft_input=(complexf*)malloc(sizeof(complexf)*fft_size);
2387          initialize_buffers();
2388          if(!sendbufsize(fft_size)) return -2;
2389  
2390          printf("setenv(\"GNUTERM\",\"X11 noraise\");y=zeros(1,%d);semilogy(y,\"ydatasource\",\"y\");\n",fft_size);
2391          for(;;)
2392          {
2393              FEOF_CHECK;
2394              fread(fft_input, sizeof(complexf), fft_size, stdin);
2395              printf("fftdata=[");
2396              //we have to swap the two parts of the array to get a valid spectrum
2397              for(int i=fft_size/2;i<fft_size;i++) printf("(%g)+(%g)*i ",iof(fft_input,i),qof(fft_input,i));
2398              for(int i=0;i<fft_size/2;i++) printf("(%g)+(%g)*i ",iof(fft_input,i),qof(fft_input,i)); 
2399              printf(
2400                  "];\n"
2401                  "y=abs(fftdata);\n"
2402                  "refreshdata;\n"
2403              );
2404          }
2405      }
2406  
2407      /*
2408        _____  _       _ _        _                       _           
2409       |  __ \(_)     (_) |      | |                     | |          
2410       | |  | |_  __ _ _| |_ __ _| |  _ __ ___   ___   __| | ___  ___ 
2411       | |  | | |/ _` | | __/ _` | | | '_ ` _ \ / _ \ / _` |/ _ \/ __|
2412       | |__| | | (_| | | || (_| | | | | | | | | (_) | (_| |  __/\__ \
2413       |_____/|_|\__, |_|\__\__,_|_| |_| |_| |_|\___/ \__,_|\___||___/
2414                  __/ |                                               
2415                 |___/                                                
2416      */
2417  
2418      if(!strcmp(argv[1],"psk31_varicode_decoder_u8_u8"))
2419      {
2420          unsigned long long status_shr = 0;
2421          unsigned char output;
2422          if(!sendbufsize(initialize_buffers())) return -2;
2423          unsigned char i=0;
2424          for(;;)
2425          {
2426              if((output=psk31_varicode_decoder_push(&status_shr, getchar()))) { putchar(output); fflush(stdout); }
2427              if(i++) continue; //do the following at every 256th execution of the loop body:
2428              FEOF_CHECK;
2429              TRY_YIELD;
2430          }
2431      }
2432  
2433      if(!strcmp(argv[1],"invert_u8_u8"))
2434      {
2435          if(!sendbufsize(initialize_buffers())) return -2;
2436          unsigned char i=0;
2437          for(;;)
2438          {
2439              putchar(!getchar());
2440              if(i++) continue; //do the following at every 256th execution of the loop body:
2441              FEOF_CHECK;
2442              TRY_YIELD;
2443          }
2444      }
2445  
2446      if(!strcmp(argv[1],"rtty_line_decoder_u8_u8"))
2447      {
2448          static rtty_baudot_decoder_t status_baudot; //created on .bss -> initialized to 0
2449          unsigned char output;
2450          if(!sendbufsize(initialize_buffers())) return -2;
2451          unsigned char i=0;
2452          for(;;)
2453          {
2454              if((output=rtty_baudot_decoder_push(&status_baudot, getchar()))) { putchar(output); fflush(stdout); }
2455              if(i++) continue; //do the following at every 256th execution of the loop body:
2456              FEOF_CHECK;
2457              TRY_YIELD;
2458          }
2459      }
2460  
2461      if(!strcmp(argv[1],"rtty_baudot2ascii_u8_u8"))
2462      {
2463          unsigned char fig_mode = 0;
2464          unsigned char output;
2465          if(!sendbufsize(initialize_buffers())) return -2;
2466          unsigned char i=0;
2467          for(;;)
2468          {
2469              if((output=rtty_baudot_decoder_lookup(&fig_mode, getchar()))) { putchar(output); fflush(stdout); }
2470              if(i++) continue; //do the following at every 256th execution of the loop body:
2471              FEOF_CHECK;
2472              TRY_YIELD;
2473          }
2474      }
2475  
2476      if(!strcmp(argv[1],"binary_slicer_f_u8"))
2477      {
2478          if(!sendbufsize(initialize_buffers())) return -2;
2479          for(;;)
2480          {
2481              FEOF_CHECK;
2482              if(!FREAD_R) break;
2483              binary_slicer_f_u8(input_buffer, (unsigned char*)output_buffer, the_bufsize);
2484              FWRITE_U8;
2485              TRY_YIELD;
2486          }
2487          return 0;
2488      }
2489  
2490      if(!strcmp(argv[1],"serial_line_decoder_f_u8")) //<samples_per_bits> [databits [stopbits]]
2491      {
2492          bigbufs=1;
2493  
2494          serial_line_t serial;
2495  
2496          if(argc<=2) return badsyntax("need required parameter (samples_per_bits)");
2497          sscanf(argv[2],"%f",&serial.samples_per_bits);
2498          if(serial.samples_per_bits<1) return badsyntax("samples_per_bits should be at least 1.");
2499          if(serial.samples_per_bits<5) fprintf(stderr, "%s: warning: this algorithm does not work well if samples_per_bits is too low. It should be at least 5.\n", argv[1]);
2500  
2501          serial.databits=8;
2502          if(argc>3) sscanf(argv[3],"%d",&serial.databits);
2503          if(serial.databits>8 || serial.databits<1) return badsyntax("databits should be between 1 and 8.");
2504  
2505          serial.stopbits=1;
2506          if(argc>4) sscanf(argv[4],"%f",&serial.stopbits);
2507          if(serial.stopbits<1) return badsyntax("stopbits should be equal or above 1.");
2508  
2509          serial.bit_sampling_width_ratio = 0.4;
2510          serial.input_used=0;
2511  
2512          if(!sendbufsize(initialize_buffers())) return -2;
2513  
2514          for(;;)
2515          {
2516              FEOF_CHECK;
2517              if(serial.input_used)
2518              {
2519                  memmove(input_buffer, input_buffer+serial.input_used, sizeof(float)*(the_bufsize-serial.input_used));
2520                  fread(input_buffer+(the_bufsize-serial.input_used), sizeof(float), serial.input_used, stdin);
2521              }
2522              else fread(input_buffer, sizeof(float), the_bufsize, stdin); //should happen only on the first run
2523              serial_line_decoder_f_u8(&serial,input_buffer, (unsigned char*)output_buffer, the_bufsize);
2524              //printf("now in | ");
2525              if(serial.input_used==0) { errhead(); fprintf(stderr, "error: serial_line_decoder_f_u8() got stuck.\n"); return -3; }
2526              //printf("now out %d | ", serial.output_size);
2527              fwrite(output_buffer, sizeof(unsigned char), serial.output_size, stdout);
2528              TRY_YIELD;
2529          }
2530      }
2531  
2532      if(!strcmp(argv[1],"pll_cc"))
2533      {
2534          pll_t pll;
2535  
2536          if(argc<=2) return badsyntax("need required parameter (pll_type)");
2537          sscanf(argv[2],"%d",(int*)&pll.pll_type);
2538          if(pll.pll_type == PLL_P_CONTROLLER)
2539          {
2540                  float alpha = 0.01;
2541                  if(argc>3) sscanf(argv[3],"%f",&alpha);
2542                  pll_cc_init_p_controller(&pll, alpha);
2543          }
2544          else if(pll.pll_type == PLL_PI_CONTROLLER)
2545          {
2546              float bandwidth = 0.01, ko = 10, kd=0.1, damping_factor = 0.707;
2547              if(argc>3) sscanf(argv[3],"%f",&bandwidth);
2548              if(argc>4) sscanf(argv[4],"%f",&damping_factor);
2549              if(argc>5) sscanf(argv[5],"%f",&ko);
2550              if(argc>6) sscanf(argv[6],"%f",&kd);
2551              pll_cc_init_pi_controller(&pll, bandwidth, ko, kd, damping_factor);
2552              errhead(); fprintf(stderr, "bw=%f damping=%f ko=%f kd=%f alpha=%f beta=%f\n", bandwidth, damping_factor, ko, kd, pll.alpha, pll.beta);
2553              //  pll.filter_taps_a[0], pll.filter_taps_a[1], pll.filter_taps_a[2], pll.filter_taps_b[0], pll.filter_taps_b[1], pll.filter_taps_b[2]);
2554          }
2555          else return badsyntax("invalid pll_type. Valid values are:\n\t1: PLL_P_CONTROLLER\n\t2: PLL_PI_CONTROLLER");
2556  
2557          if(!sendbufsize(initialize_buffers())) return -2;
2558  
2559          for(;;)
2560          {
2561              FEOF_CHECK;
2562              FREAD_C;
2563              //fprintf(stderr, "| i");
2564              // pll_cc(&pll, (complexf*)input_buffer, output_buffer, NULL, the_bufsize);
2565              // fwrite(output_buffer, sizeof(float), the_bufsize, stdout);
2566              pll_cc(&pll, (complexf*)input_buffer, NULL, (complexf*)output_buffer, the_bufsize);
2567              fwrite(output_buffer, sizeof(complexf), the_bufsize, stdout);
2568              //fprintf(stderr, "| o");
2569              TRY_YIELD;
2570          }
2571      }
2572  
2573      if(!strcmp(argv[1],"timing_recovery_cc")) //<algorithm> <decimation> [mu [max_error [--add_q [--output_error | --output_indexes | --octave <show_every_nth> | --octave_save <show_every_nth> <directory> ]]]] \n"
2574      {
2575          if(argc<=2) return badsyntax("need required parameter (algorithm)");
2576          timing_recovery_algorithm_t algorithm = timing_recovery_get_algorithm_from_string(argv[2]);
2577          //if(algorithm == TIMING_RECOVERY_ALGORITHM_DEFAULT) 
2578          //  fprintf(stderr,"#timing_recovery_cc: algorithm = %s\n",timing_recovery_get_string_from_algorithm(algorithm));
2579          if(argc<=3) return badsyntax("need required parameter (decimation factor)");
2580          int decimation;
2581          sscanf(argv[3],"%d",&decimation);
2582          if(decimation<=4 || decimation&3) return badsyntax("decimation factor should be a positive integer divisible by 4");
2583  
2584          float loop_gain = 0.5;
2585          if(argc>4) sscanf(argv[4],"%f",&loop_gain);
2586  
2587          float max_error = 2;
2588          if(argc>5) sscanf(argv[5],"%f",&max_error);
2589  
2590          int add_q = !!(argc>=7 && !strcmp(argv[6], "--add_q"));
2591  
2592          int debug_every_nth = -1;
2593          int output_error = 0;
2594          int output_indexes = 0;
2595          int octave_save = 0;
2596          char* octave_save_path = NULL;
2597          if(argc>=8+add_q && (!strcmp(argv[6+add_q], "--octave") || (octave_save = !strcmp(argv[6+add_q], "--octave_save")))) 
2598          {
2599              debug_every_nth = atoi(argv[7+add_q]);
2600              if(debug_every_nth<0) return badsyntax("debug_every_nth should be >= 0");
2601          }
2602          if(octave_save)
2603          {
2604              if(argc>=9+add_q) octave_save_path = argv[8+add_q]; 
2605              else octave_save_path = "figs";
2606          }
2607          if(debug_every_nth<0) { errhead(); fprintf(stderr, "--add_q mode on\n"); }
2608  
2609          if(argc>=(7+add_q) && !strcmp(argv[6+add_q], "--output_error")) output_error = 1;
2610          float* timing_error = NULL;
2611          if(output_error) timing_error = (float*)malloc(sizeof(float)*the_bufsize);
2612          if(output_error) { errhead(); fprintf(stderr, "--output_error mode\n"); }
2613  
2614          if(argc>=(7+add_q) && !strcmp(argv[6+add_q], "--output_indexes")) output_indexes = 1;
2615          unsigned* sampled_indexes = NULL;
2616          if(output_indexes) sampled_indexes = (unsigned*)malloc(sizeof(float)*the_bufsize);
2617          if(output_indexes) { errhead(); fprintf(stderr, "--output_indexes mode\n"); }
2618  
2619          if(!initialize_buffers()) return -2;
2620          sendbufsize(the_bufsize/decimation);
2621  
2622          timing_recovery_state_t state = timing_recovery_init(algorithm, decimation, add_q, loop_gain, max_error, debug_every_nth, octave_save_path);
2623  
2624          FREAD_C;
2625          unsigned buffer_start_counter = 0;
2626          for(;;)
2627          {
2628              FEOF_CHECK;
2629              timing_recovery_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, timing_error, (int*)sampled_indexes, &state);
2630              //fprintf(stderr, "trcc is=%d, os=%d, ip=%d\n",the_bufsize, state.output_size, state.input_processed);
2631              if(timing_error) fwrite(timing_error, sizeof(float), state.output_size, stdout);
2632              else if(sampled_indexes) 
2633              {
2634                  for(int i=0;i<state.output_size;i++) sampled_indexes[i]+=buffer_start_counter;
2635                  fwrite(sampled_indexes, sizeof(unsigned), state.output_size, stdout);
2636              }
2637              else fwrite(output_buffer, sizeof(complexf), state.output_size, stdout);
2638              TRY_YIELD;
2639              //fprintf(stderr, "state.input_processed = %d\n", state.input_processed);
2640              buffer_start_counter+=state.input_processed;
2641              memmove((complexf*)input_buffer,((complexf*)input_buffer)+state.input_processed,(the_bufsize-state.input_processed)*sizeof(complexf)); //memmove lets the source and destination overlap
2642              fread(((complexf*)input_buffer)+(the_bufsize-state.input_processed), sizeof(complexf), state.input_processed, stdin);
2643              //fprintf(stderr,"iskip=%d state.output_size=%d start=%x target=%x skipcount=%x \n",state.input_processed,state.output_size,input_buffer, ((complexf*)input_buffer)+(BIG_BUFSIZE-state.input_processed),(BIG_BUFSIZE-state.input_processed));
2644          }
2645      }
2646  
2647      if(!strcmp(argv[1],"octave_complex_c"))
2648      {
2649          if(argc<=2) return badsyntax("need required parameter (samples_to_plot)");
2650          int samples_to_plot = 0;
2651          sscanf(argv[2], "%d", &samples_to_plot);
2652          if(samples_to_plot<=0) return badsyntax("Number of samples to plot should be > 0");
2653          if(argc<=3) return badsyntax("need required parameter (out_of_n_samples)");
2654          int out_of_n_samples = 0;
2655          sscanf(argv[3], "%d", &out_of_n_samples);
2656          if(out_of_n_samples<samples_to_plot) return badsyntax("out_of_n_samples should be < samples_to_plot");
2657          int mode2d = 0;
2658          if(argc>4) mode2d = !strcmp(argv[4], "--2d"); 
2659          complexf* read_buf = (complexf*)malloc(sizeof(complexf)*the_bufsize);
2660  
2661          if(!sendbufsize(initialize_buffers())) return -2;
2662          for(;;)
2663          {
2664              fread(read_buf, sizeof(complexf), samples_to_plot, stdin);          
2665              printf("N = %d;\nisig = [", samples_to_plot);
2666              for(int i=0;i<samples_to_plot;i++) printf("%f ", iof(read_buf, i));
2667              printf("];\nqsig = [");
2668              for(int i=0;i<samples_to_plot;i++) printf("%f ", qof(read_buf, i));
2669              printf("];\nzsig = [0:N-1];\n");
2670              if(mode2d) printf("subplot(2,1,1);\nplot(zsig,isig);\nsubplot(2,1,2);\nplot(zsig,qsig);\n");
2671              else printf("plot3(isig,zsig,qsig);\n");
2672              //printf("xlim([-1 1]);\nzlim([-1 1]);\n");
2673              fflush(stdout);
2674              //if(fseek(stdin, (out_of_n_samples - samples_to_plot)*sizeof(complexf), SEEK_CUR)<0) { perror("fseek error"); return -3; } //this cannot be used on stdin
2675              for(int seek_remain=out_of_n_samples-samples_to_plot;seek_remain>0;seek_remain-=samples_to_plot)
2676              {
2677                  fread(read_buf, sizeof(complexf), MIN_M(samples_to_plot,seek_remain), stdin);
2678              }
2679              FEOF_CHECK;
2680              TRY_YIELD;
2681          }
2682      }
2683  
2684      if(!strcmp(argv[1],"psk_modulator_u8_c")) //<n_psk>
2685      {
2686          int n_psk;
2687          if(argc<=2) return badsyntax("need required parameter (n_psk)");
2688          sscanf(argv[2],"%d",&n_psk);
2689          if(n_psk<=0 || n_psk>256) return badsyntax("n_psk should be between 1 and 256");
2690  
2691          if(!initialize_buffers()) return -2;
2692          sendbufsize(the_bufsize);
2693  
2694          for(;;)
2695          {
2696              FEOF_CHECK;
2697              fread((unsigned char*)input_buffer, sizeof(unsigned char), the_bufsize, stdin);
2698              psk_modulator_u8_c((unsigned char*)input_buffer, (complexf*)output_buffer, the_bufsize, n_psk);
2699              FWRITE_C;
2700              TRY_YIELD;
2701          }
2702      }
2703  
2704      if(!strcmp(argv[1],"duplicate_samples_ntimes_u8_u8")) //<sample_size_bytes> <ntimes>
2705      {
2706          int sample_size_bytes = 0, ntimes = 0;
2707          if(argc<=2) return badsyntax("need required parameter (sample_size_bytes)");
2708          sscanf(argv[2],"%d",&sample_size_bytes);    
2709          if(sample_size_bytes<=0) return badsyntax("sample_size_bytes should be >0");
2710          if(argc<=3) return badsyntax("need required parameter (ntimes)");
2711          sscanf(argv[3],"%d",&ntimes);   
2712          if(ntimes<=0) return badsyntax("ntimes should be >0");
2713          if(!initialize_buffers()) return -2;
2714          sendbufsize(the_bufsize*ntimes);
2715          unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*sample_size_bytes);
2716          unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*sample_size_bytes*ntimes);
2717          for(;;)
2718          {
2719              FEOF_CHECK;
2720              fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize*sample_size_bytes, stdin);
2721              duplicate_samples_ntimes_u8_u8(local_input_buffer, local_output_buffer, the_bufsize*sample_size_bytes, sample_size_bytes, ntimes);
2722              fwrite((void*)local_output_buffer, sizeof(unsigned char), the_bufsize*sample_size_bytes*ntimes, stdout);
2723              TRY_YIELD;
2724          }
2725      }
2726  
2727      if(!strcmp(argv[1],"psk31_interpolate_sine_cc")) //<interpolation>
2728      {
2729          int interpolation;
2730          if(argc<=2) return badsyntax("need required parameter (interpolation)");
2731          sscanf(argv[2],"%d",&interpolation);    
2732          if(interpolation<=0) return badsyntax("interpolation should be >0"); 
2733          if(!initialize_buffers()) return -2;
2734          sendbufsize(the_bufsize*interpolation);
2735          complexf* local_output_buffer = (complexf*)malloc(sizeof(complexf)*the_bufsize*interpolation);
2736          complexf last_input;
2737          iof(&last_input,0) = 0;
2738          qof(&last_input,0) = 0;
2739          for(;;)
2740          {
2741              FEOF_CHECK;
2742              FREAD_C;
2743              last_input = psk31_interpolate_sine_cc((complexf*)input_buffer, local_output_buffer, the_bufsize, interpolation, last_input);
2744              fwrite((void*)local_output_buffer, sizeof(complexf), the_bufsize*interpolation, stdout);
2745              TRY_YIELD;
2746          }
2747      }
2748  
2749      if(!strcmp(argv[1],"pack_bits_1to8_u8_u8")) 
2750      {
2751          if(!initialize_buffers()) return -2;
2752          sendbufsize(the_bufsize*8);
2753          unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize);
2754          unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize*8);
2755          for(;;)
2756          {
2757              FEOF_CHECK;
2758              fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin);
2759              pack_bits_1to8_u8_u8(local_input_buffer, local_output_buffer, the_bufsize);
2760              fwrite((void*)local_output_buffer, sizeof(unsigned char), the_bufsize*8, stdout);
2761              TRY_YIELD;
2762          }
2763      }
2764  
2765      if(!strcmp(argv[1],"pack_bits_8to1_u8_u8")) 
2766      {
2767          if(!initialize_buffers()) return -2;
2768          sendbufsize(1);
2769          char local_input_buffer[8];
2770          for(;;)
2771          {
2772              FEOF_CHECK;
2773              fread((void*)local_input_buffer, sizeof(unsigned char), 8, stdin);
2774              unsigned char c = pack_bits_8to1_u8_u8(local_input_buffer);
2775              fwrite(&c, sizeof(unsigned char), 1, stdout);
2776              TRY_YIELD;
2777          }
2778      }
2779  
2780      if(!strcmp(argv[1],"psk31_varicode_encoder_u8_u8")) 
2781      {
2782          if(!initialize_buffers()) return -2;
2783          sendbufsize(the_bufsize*8);
2784          int output_max_size=the_bufsize*30;
2785          int output_size;
2786          int input_processed;
2787          unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize);
2788          unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*output_max_size);
2789          fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin);
2790          for(;;)
2791          {
2792              psk31_varicode_encoder_u8_u8(local_input_buffer, local_output_buffer, the_bufsize, output_max_size, &input_processed, &output_size);
2793              //fprintf(stderr, "os = %d\n", output_size);
2794              fwrite((void*)local_output_buffer, sizeof(unsigned char), output_size, stdout);
2795              FEOF_CHECK;
2796              memmove(local_input_buffer, local_input_buffer+input_processed, the_bufsize-input_processed); 
2797              fread(input_buffer+the_bufsize-input_processed, sizeof(unsigned char), input_processed, stdin);
2798              TRY_YIELD;
2799          }
2800      }
2801  
2802      if(!strcmp(argv[1],"dump_u8")) 
2803      {
2804          if(!initialize_buffers()) return -2;
2805          sendbufsize(the_bufsize*3);
2806          unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize);
2807          for(;;)
2808          {
2809              FEOF_CHECK;
2810              fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin);
2811              for(int i=0;i<the_bufsize;i++) printf("%02x ", local_input_buffer[i]);
2812              TRY_YIELD;
2813          }
2814      }
2815  
2816      int differential_codec_encode = 0;
2817      if( (differential_codec_encode = !strcmp(argv[1],"differential_encoder_u8_u8")) || (!strcmp(argv[1],"differential_decoder_u8_u8")) )
2818      {
2819          if(!initialize_buffers()) return -2;
2820          sendbufsize(the_bufsize);
2821          unsigned char* local_input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize);
2822          unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize);
2823          unsigned char state = 0;
2824          for(;;)
2825          {
2826              FEOF_CHECK;
2827              fread((void*)local_input_buffer, sizeof(unsigned char), the_bufsize, stdin);
2828              state = differential_codec(local_input_buffer, local_output_buffer, the_bufsize, differential_codec_encode, state);
2829              fwrite((void*)local_output_buffer, sizeof(unsigned char), the_bufsize, stdout);
2830              TRY_YIELD;
2831          }
2832      }
2833  
2834      if(!strcmp(argv[1],"bpsk_costas_loop_cc")) //<loop_bandwidth> <damping_factor> [--dd | --decision_directed] [--output_error | --output_dphase | --output_nco | --output_combined <error_file> <dphase_file> <nco_file>]
2835      {
2836          float loop_bandwidth;
2837          if(argc<=2) return badsyntax("need required parameter (loop_bandwidth)");
2838          sscanf(argv[2],"%f",&loop_bandwidth);
2839  
2840          float damping_factor;
2841          if(argc<=3) return badsyntax("need required parameter (damping_factor)");
2842          sscanf(argv[3],"%f",&damping_factor);
2843  
2844          int decision_directed = !!(argc>4 && (!strcmp(argv[4], "--dd") || !strcmp(argv[5], "--decision_directed")));
2845          if(decision_directed) { errhead(); fprintf(stderr, "decision directed mode\n"); }
2846  
2847          int output_error    =                  !!(argc>4+decision_directed && (!strcmp(argv[4+decision_directed], "--output_error")));
2848          int output_dphase   = !output_error  & !!(argc>4+decision_directed && (!strcmp(argv[4+decision_directed], "--output_dphase")));
2849          int output_nco      = !output_dphase & !!(argc>4+decision_directed && (!strcmp(argv[4+decision_directed], "--output_nco")));
2850          int output_combined = !output_nco    & !!(argc>4+decision_directed && (!strcmp(argv[4+decision_directed], "--output_combined")));
2851  
2852  
2853          bpsk_costas_loop_state_t state;
2854          init_bpsk_costas_loop_cc(&state, decision_directed, damping_factor, loop_bandwidth);
2855          errhead(); fprintf(stderr, "alpha = %f, beta = %f\n", state.alpha, state.beta);
2856  
2857          if(!initialize_buffers()) return -2;
2858          sendbufsize(the_bufsize);
2859  
2860          float* buffer_output_error  = (!(output_combined || output_error))  ? NULL : (float*)malloc(sizeof(float)*the_bufsize);
2861          float* buffer_output_dphase = (!(output_combined || output_dphase)) ? NULL : (float*)malloc(sizeof(float)*the_bufsize);
2862          complexf* buffer_output_nco = (!(output_combined || output_nco))    ? NULL : (complexf*)malloc(sizeof(complexf)*the_bufsize);
2863  
2864          FILE* file_output_error = NULL;
2865          FILE* file_output_dphase = NULL;
2866          FILE* file_output_nco = NULL;
2867          if(output_combined)
2868          {
2869              if(!(argc>4+decision_directed+3)) { return badsyntax("need required parameters after --output_combined: <error_file> <dphase_file> <nco_file>"); }
2870              file_output_error  = fopen(argv[4+decision_directed+1], "w");
2871              file_output_dphase = fopen(argv[4+decision_directed+2], "w");
2872              file_output_nco    = fopen(argv[4+decision_directed+3], "w");
2873          }
2874  
2875          for(;;)
2876          {
2877              FEOF_CHECK;
2878              FREAD_C;
2879              bpsk_costas_loop_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, 
2880                      buffer_output_error, buffer_output_dphase, buffer_output_nco, 
2881                      &state);
2882              if(output_error) fwrite(buffer_output_error, sizeof(float), the_bufsize, stdout);
2883              else if(output_dphase) fwrite(buffer_output_dphase, sizeof(float), the_bufsize, stdout);
2884              else if(output_nco) fwrite(buffer_output_nco, sizeof(complexf), the_bufsize, stdout);
2885              else 
2886              {
2887                  if(output_combined) 
2888                  {
2889                      fwrite(buffer_output_error, sizeof(float), the_bufsize, file_output_error);
2890                      fwrite(buffer_output_dphase, sizeof(float), the_bufsize, file_output_dphase);
2891                      fwrite(buffer_output_nco, sizeof(complexf), the_bufsize, file_output_nco);
2892                  }
2893                  FWRITE_C; 
2894              }
2895              TRY_YIELD;
2896          }
2897          fclose(file_output_error);
2898          fclose(file_output_dphase);
2899          fclose(file_output_nco);
2900      }
2901  
2902      if(!strcmp(argv[1],"simple_agc_cc")) //<rate> [reference [max_gain]] 
2903      {
2904          float rate;
2905          if(argc<=2) return badsyntax("need required parameter (rate)");
2906          sscanf(argv[2],"%f",&rate);
2907          if(rate<=0) return badsyntax("rate should be > 0");
2908  
2909          float reference = 1.;
2910          if(argc>3) sscanf(argv[3],"%f",&reference);
2911          if(reference<=0) return badsyntax("reference should be > 0");
2912  
2913          float max_gain = 65535.;
2914          if(argc>4) sscanf(argv[4],"%f",&max_gain);
2915          if(max_gain<=0) return badsyntax("max_gain should be > 0");
2916  
2917          float current_gain = 1.;
2918  
2919          if(!initialize_buffers()) return -2;
2920          sendbufsize(the_bufsize);
2921  
2922          for(;;)
2923          {
2924              FEOF_CHECK;
2925              FREAD_C;
2926              simple_agc_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, rate, reference, max_gain, &current_gain);
2927              FWRITE_C;
2928              TRY_YIELD;
2929          }
2930      }
2931  
2932      if(!strcmp(argv[1],"firdes_peak_c")) //<rate> <length> [window [--octave]]
2933      {
2934          //Process the params
2935          if(argc<=3) return badsyntax("need required parameters (rate, length)");
2936  
2937          float rate;
2938          sscanf(argv[2],"%g",&rate);
2939          int length;
2940          sscanf(argv[3],"%d",&length);
2941          if(length%2==0) return badsyntax("number of symmetric FIR filter taps should be odd");
2942  
2943          window_t window = WINDOW_DEFAULT;
2944          if(argc>=5)
2945          {
2946              window=firdes_get_window_from_string(argv[4]);
2947          }
2948          else { errhead(); fprintf(stderr,"window = %s\n",firdes_get_string_from_window(window)); }
2949  
2950          int octave=(argc>=6 && !strcmp("--octave",argv[5]));
2951  
2952          complexf* taps=(complexf*)malloc(sizeof(complexf)*length);
2953  
2954          //Make the filter
2955          firdes_add_peak_c(taps, length, rate, window, 0, 1);
2956  
2957          //Do the output
2958          if(octave) printf("taps=[");
2959          for(int i=0;i<length;i++) printf("(%g)+(%g)*i ",iof(taps,i),qof(taps,i));
2960          int fft_length=1024;
2961          while(fft_length<length) fft_length*=2;
2962          //if(octave) printf("];\n");
2963          if(octave) printf(
2964              "];figure(\"Position\",[0 0 1000 1000]);fser=fft([taps,zeros(1,%d)]);ampl=abs(fser).^2;halfindex=floor(1+size(ampl)(2)/2);\n"
2965              "amplrev=[ampl(halfindex:end),ampl(1:halfindex)];\n" //we have to swap the output of FFT
2966              "subplot(2,1,1);plot(amplrev);\n"
2967              "subplot(2,1,2);plot(arg(fser));\n",fft_length-length);
2968  
2969          //Wait forever, so that octave won't close just after popping up the window.
2970          //You can close it with ^C.
2971          if(octave) { fflush(stdout); getchar(); }
2972          return 0;
2973      }
2974   
2975      if(!strcmp(argv[1],"peaks_fir_cc")) //<taps_length> <peak_rate × N>
2976      {
2977          //rule of thumb: bw = 2/taps_length,   which does not equal to transition_bw
2978  
2979          if(argc<=2) return badsyntax("need required parameter (taps_length)");
2980          int taps_length;
2981          sscanf(argv[2],"%d",&taps_length);
2982  
2983          int num_peaks = argc-3;
2984          float* peak_rate = (float*)malloc(sizeof(float)*num_peaks);
2985          for(int i=0;i<num_peaks;i++)
2986              sscanf(argv[3+i], "%f", peak_rate+i);
2987          if(num_peaks<=0) return badsyntax("need required parameter (peak_rate) once or multiple times");
2988          //for(int i=0;i<num_peaks;i++) fprintf(stderr, "%f\n", peak_rate[i]);
2989          fflush(stderr);
2990  
2991          window_t window = WINDOW_DEFAULT;
2992  
2993          if(!initialize_buffers()) return -2;
2994          sendbufsize(the_bufsize);
2995          if(the_bufsize - taps_length <= 0 ) return badsyntax("taps_length is below buffer size, decrease taps_length");
2996  
2997          complexf* taps = (complexf*)calloc(sizeof(complexf),taps_length);
2998          for(int i=0; i<num_peaks; i++)
2999          {
3000              //fprintf(stderr, "nr = %d\n", i==num_peaks-1);
3001              firdes_add_peak_c(taps, taps_length, peak_rate[i], window, 1, i==num_peaks-1);
3002          }
3003  
3004          int output_size=0;
3005          FREAD_C;
3006          for(;;)
3007          {
3008              FEOF_CHECK;
3009              output_size = apply_fir_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, taps, taps_length);
3010              fwrite(output_buffer, sizeof(complexf), output_size, stdout);
3011              //fprintf(stderr, "os = %d, is = %d\n", output_size, the_bufsize);
3012              TRY_YIELD;
3013              memmove((complexf*)input_buffer,((complexf*)input_buffer)+output_size,(the_bufsize-output_size)*sizeof(complexf)); 
3014              fread(((complexf*)input_buffer)+(the_bufsize-output_size), sizeof(complexf), output_size, stdin);
3015          }
3016      }
3017  
3018      if(!strcmp(argv[1], "repeat_u8"))
3019      {
3020          if(argc<=2) return badsyntax("no data to repeat");
3021          unsigned char* repeat_buffer = (unsigned char*)malloc(sizeof(unsigned char)*(argc-2));
3022          if(!initialize_buffers()) return -2;
3023          sendbufsize(the_bufsize); //this is really (c-2) but this is a very fast source block so it makes no sense to send out a small number here
3024          for(int i=0;i<argc-2;i++)
3025          {
3026              FEOF_CHECK;
3027              int current_val;
3028              sscanf(argv[i+2], "%d", &current_val); 
3029              repeat_buffer[i]=current_val;
3030              TRY_YIELD;
3031          }
3032          for(;;) fwrite(repeat_buffer, sizeof(unsigned char), argc-2, stdout);
3033      }
3034  
3035      if(!strcmp(argv[1], "awgn_cc"))
3036      {
3037          FILE* urandom = init_get_random_samples_f();
3038          if(argc<=2) return badsyntax("required parameter <snr_db> is missing.");
3039          float snr_db = 0;
3040          sscanf(argv[2],"%f",&snr_db);
3041          FILE* awgnfile = NULL; 
3042          if(argc>=5 && !strcmp(argv[3],"--awgnfile")) 
3043          {
3044              awgnfile=fopen(argv[4], "r");
3045              if(!awgnfile) return badsyntax("failed to open the --awgnfile");
3046          }
3047          int parnumadd=2*(!!awgnfile);
3048          int snrshow = 0;
3049          if(argc>=4+parnumadd && !strcmp(argv[3+parnumadd],"--snrshow")) snrshow = 1;
3050          float signal_amplitude_per_noise = pow(10,snr_db/20);
3051          float a_signal=signal_amplitude_per_noise/(signal_amplitude_per_noise+1.0);
3052          float a_noise=1.0/(signal_amplitude_per_noise+1.0);
3053          errhead(); fprintf(stderr, "a_signal = %f, a_noise = %f\n", a_signal, a_noise);
3054          if(!initialize_buffers()) return -2;
3055          sendbufsize(the_bufsize); 
3056          complexf* awgn_buffer = (complexf*)malloc(sizeof(complexf)*the_bufsize);
3057          for(;;)
3058          {
3059              FEOF_CHECK;
3060              FREAD_C;
3061              //get_awgn_samples_f((float*)awgn_buffer, the_bufsize*2, urandom);
3062              if(!awgnfile) get_random_gaussian_samples_c(awgn_buffer, the_bufsize, urandom);
3063              else 
3064              {
3065                  for(;;)
3066                  {
3067                      int items_read=fread(awgn_buffer, sizeof(complexf), the_bufsize, awgnfile);
3068                      if(items_read<the_bufsize) rewind(awgnfile);
3069                      else break;
3070                  }
3071              }
3072              /*if(snrshow) 
3073              {
3074                  float power_signal = total_logpower_cf((complexf*)input_buffer, the_bufsize);
3075                  float power_noise = total_logpower_cf(awgn_buffer, the_bufsize);
3076                  fprintf(stderr, "csdr awgn_cc: at the beginning, power_signal = %f dB, power_noise = %f dB\n", power_signal, power_noise);
3077              }*/
3078              gain_ff(input_buffer, input_buffer, the_bufsize*2, a_signal);
3079              gain_ff((float*)awgn_buffer, (float*)awgn_buffer, the_bufsize*2, a_noise*0.707);
3080              if(snrshow)
3081              {
3082                  float power_signal = total_logpower_cf((complexf*)input_buffer, the_bufsize);
3083                  float power_noise = total_logpower_cf(awgn_buffer, the_bufsize);
3084                  //fprintf(stderr, "csdr awgn_cc: after gain_ff, power_signal = %f dB, power_noise = %f dB\n", power_signal, power_noise);
3085                  errhead(); fprintf(stderr, "SNR = %f dB\n", power_signal - power_noise);
3086              }
3087              add_ff(input_buffer, (float*)awgn_buffer, (float*)output_buffer, the_bufsize*2);
3088              FWRITE_C;
3089              TRY_YIELD;
3090          }
3091      }
3092  
3093      if(!strcmp(argv[1], "uniform_noise_f"))
3094      {
3095          FILE* urandom = init_get_random_samples_f();
3096          if(!initialize_buffers()) return -2;
3097          sendbufsize(the_bufsize); 
3098          for(;;)
3099          {
3100              FEOF_CHECK;
3101              get_random_samples_f(output_buffer, the_bufsize, urandom);
3102              FWRITE_R;
3103              TRY_YIELD;
3104          }
3105      }
3106  
3107      if(!strcmp(argv[1], "gaussian_noise_c"))
3108      {
3109          FILE* urandom = init_get_random_samples_f();
3110          if(!initialize_buffers()) return -2;
3111          sendbufsize(the_bufsize); 
3112          for(;;)
3113          {
3114              FEOF_CHECK;
3115              get_random_gaussian_samples_c((complexf*)output_buffer, the_bufsize, urandom);
3116              FWRITE_C;
3117              TRY_YIELD;
3118          }
3119      }
3120  
3121      if(!strcmp(argv[1], "normalized_timing_variance_u32_f")) //<samples_per_symbol> <initial_sample_offset> [--debug]
3122      {
3123          int samples_per_symbol = 0;
3124          if(argc<=2) return badsyntax("required parameter <samples_per_symbol> is missing.");
3125          sscanf(argv[2],"%d",&samples_per_symbol);
3126  
3127          int initial_sample_offset = 0;
3128          if(argc<=3) return badsyntax("required parameter <initial_sample_offset> is missing.");
3129          sscanf(argv[3],"%d",&initial_sample_offset);
3130  
3131          int debug_print = 0;
3132          if(argc>4 && !strcmp(argv[4],"--debug")) debug_print = 1; 
3133  
3134          if(!initialize_buffers()) return -2;
3135          sendbufsize(the_bufsize); 
3136          float* temp_buffer = (float*)malloc(sizeof(float)*the_bufsize);
3137          for(;;)
3138          {
3139              FEOF_CHECK;
3140              FREAD_R; //doesn't count, reads 4 bytes per sample anyway
3141              float nv = normalized_timing_variance_u32_f((unsigned*)input_buffer, temp_buffer, the_bufsize, samples_per_symbol, initial_sample_offset, debug_print);
3142              fwrite(&nv, sizeof(float), 1, stdout);
3143              errhead(); fprintf(stderr, "normalized variance = %f\n", nv);
3144              TRY_YIELD;
3145          }
3146      }
3147  
3148      if(!strcmp(argv[1], "add_n_zero_samples_at_beginning_f")) //<n_zero_samples>
3149      {
3150          int n_zero_samples = 0;
3151          if(argc<=2) return badsyntax("required parameter <n_zero_samples> is missing.");
3152          sscanf(argv[2],"%d",&n_zero_samples);
3153          if(!sendbufsize(initialize_buffers())) return -2;
3154          float* zeros=(float*)calloc(sizeof(float),n_zero_samples);
3155          fwrite(zeros, sizeof(float), n_zero_samples, stdout);
3156          clone_(the_bufsize);
3157      }
3158  
3159      int pulse_shaping_filter_which = 0;
3160      if(
3161              (!strcmp(argv[1], "firdes_pulse_shaping_filter_f") && (pulse_shaping_filter_which = 1)) ||
3162              (!strcmp(argv[1], "pulse_shaping_filter_cc") && (pulse_shaping_filter_which = 2))
3163      ) //(RRC <samples_per_symbol> <num_taps> <beta> | COSINE <samples_per_symbol>)
3164      {
3165          if(argc<=2) return badsyntax("required parameter <pulse_shaping_filter_type> is missing.");
3166          matched_filter_type_t type = matched_filter_get_type_from_string(argv[2]);
3167  
3168          int samples_per_symbol = 0;
3169          if(argc<=3) return badsyntax("required parameter <samples_per_symbol> is missing.");
3170          sscanf(argv[3],"%d",&samples_per_symbol);
3171  
3172          int num_taps = 0;
3173          if(type!=MATCHED_FILTER_COSINE)
3174          {
3175              if(argc<=4) return badsyntax("required parameter <num_taps> is missing.");
3176              sscanf(argv[4],"%d",&num_taps);
3177          }
3178          else num_taps = (2*samples_per_symbol)+1;
3179  
3180          float beta = 0;
3181          if(type==MATCHED_FILTER_RRC)
3182          {
3183              if(argc<=5) return badsyntax("required parameter <beta> is missing.");
3184              sscanf(argv[5],"%f",&beta);
3185          }
3186  
3187          float* taps = (float*)malloc(sizeof(float)*num_taps);
3188          switch(type)
3189          {
3190          case MATCHED_FILTER_RRC:
3191              firdes_rrc_f(taps, num_taps, samples_per_symbol, beta);
3192              break;
3193          case MATCHED_FILTER_COSINE:
3194              firdes_cosine_f(taps, num_taps, samples_per_symbol);
3195              break;
3196          }
3197          //fprintf(stderr, "beta = %f, num_taps = %d, samples_per_symbol = %d\n", beta, num_taps, samples_per_symbol);
3198  
3199          if(!sendbufsize(initialize_buffers())) return -2;
3200  
3201          if(pulse_shaping_filter_which==1)
3202          {
3203              for(int i=0;i<num_taps;i++) printf("%f ", taps[i]);
3204              return 0;
3205          }
3206  
3207          int output_size=0;
3208          FREAD_C;
3209          for(;;)
3210          {
3211              FEOF_CHECK;
3212              output_size = apply_real_fir_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, taps, num_taps);
3213              fwrite(output_buffer, sizeof(complexf), output_size, stdout);
3214              //fprintf(stderr, "os = %d, is = %d, num_taps = %d\n", output_size, the_bufsize, num_taps);
3215              TRY_YIELD;
3216              memmove((complexf*)input_buffer,((complexf*)input_buffer)+output_size,(the_bufsize-output_size)*sizeof(complexf)); 
3217              fread(((complexf*)input_buffer)+(the_bufsize-output_size), sizeof(complexf), output_size, stdin);
3218          }
3219      }
3220  
3221      if(!strcmp(argv[1], "generic_slicer_f_u8")) //<n_symbols>
3222      {
3223          int n_symbols = 0;
3224          if(argc<=2) return badsyntax("required parameter <n_symbols> is missing.");
3225          sscanf(argv[2],"%d",&n_symbols);
3226          if(!sendbufsize(initialize_buffers())) return -2;
3227          for(;;)
3228          {
3229              FEOF_CHECK;
3230              if(!FREAD_R) break;
3231              generic_slicer_f_u8(input_buffer, (unsigned char*)output_buffer, the_bufsize, n_symbols);
3232              FWRITE_U8;
3233              TRY_YIELD;
3234          }
3235          return 0;
3236      }
3237  
3238      if(!strcmp(argv[1], "plain_interpolate_cc")) //<interpolation>
3239      {
3240          int interpolation = 0;
3241          if(argc<=2) return badsyntax("required parameter <interpolation> is missing.");
3242          sscanf(argv[2],"%d",&interpolation);
3243          if(!sendbufsize(interpolation*initialize_buffers())) return -2;
3244          complexf* plainint_output_buffer = (complexf*)malloc(sizeof(complexf)*the_bufsize*interpolation);
3245          for(;;)
3246          {
3247              FEOF_CHECK;
3248              FREAD_C;
3249              plain_interpolate_cc((complexf*)input_buffer, plainint_output_buffer, the_bufsize, interpolation);
3250              fwrite(plainint_output_buffer, sizeof(float)*2, the_bufsize*interpolation, stdout);
3251              TRY_YIELD;
3252          }
3253          return 0;
3254      }
3255  
3256      if(!strcmp(argv[1], "dbpsk_decoder_c_u8")) 
3257      {
3258          if(!sendbufsize(initialize_buffers())) return -2;
3259          unsigned char* local_output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*the_bufsize);
3260          for(;;)
3261          {
3262              FEOF_CHECK;
3263              FREAD_C;
3264              dbpsk_decoder_c_u8((complexf*)input_buffer, local_output_buffer, the_bufsize);
3265              fwrite(local_output_buffer, sizeof(unsigned char), the_bufsize, stdout);
3266              TRY_YIELD;
3267          }
3268          return 0;
3269      }
3270  
3271      if(!strcmp(argv[1], "bfsk_demod_cf")) //<spacing> <filter_length> 
3272      {
3273          float frequency_shift = 0;
3274          if(argc<=2) return badsyntax("required parameter <frequency_shift> is missing.");
3275          sscanf(argv[2],"%f",&frequency_shift);
3276  
3277          int filter_length = 0;
3278          if(argc<=3) return badsyntax("required parameter <filter_length> is missing.");
3279          sscanf(argv[3],"%d",&filter_length);
3280  
3281          complexf* mark_filter = (complexf*)malloc(sizeof(complexf)*filter_length);
3282          complexf* space_filter = (complexf*)malloc(sizeof(complexf)*filter_length);
3283          firdes_add_peak_c(mark_filter, filter_length, frequency_shift/2, WINDOW_DEFAULT, 0, 1);
3284          firdes_add_peak_c(space_filter, filter_length, -frequency_shift/2, WINDOW_DEFAULT, 0, 1);
3285  
3286          if(!sendbufsize(initialize_buffers())) return -2;
3287  
3288          int input_skip=0;
3289          int output_size=0;
3290          FREAD_C;
3291          for(;;)
3292          {
3293              FEOF_CHECK;
3294              output_size=bfsk_demod_cf((complexf*)input_buffer, output_buffer, the_bufsize, mark_filter, space_filter, filter_length);
3295              fwrite(output_buffer, sizeof(float), output_size, stdout);
3296              TRY_YIELD;
3297              memmove((complexf*)input_buffer,((complexf*)input_buffer)+output_size,(the_bufsize-output_size)*sizeof(complexf));
3298              fread(((complexf*)input_buffer)+(the_bufsize-output_size), sizeof(complexf), output_size, stdin);
3299          }
3300          return 0;
3301      }
3302  
3303      if(!strcmp(argv[1], "add_const_cc")) //<i> <q>
3304      {
3305          complexf x;
3306          if(argc<=2) return badsyntax("required parameter <add_i> is missing.");
3307          sscanf(argv[2],"%f",&iofv(x));
3308          if(argc<=2) return badsyntax("required parameter <add_q> is missing.");
3309          sscanf(argv[2],"%f",&qofv(x));
3310  
3311          if(!sendbufsize(initialize_buffers())) return -2;
3312          for(;;)
3313          {
3314              FEOF_CHECK;
3315              FREAD_C;
3316              add_const_cc((complexf*)input_buffer, (complexf*)output_buffer, the_bufsize, x);
3317              FWRITE_C;
3318              TRY_YIELD;
3319          }
3320          return 0;
3321      }
3322  
3323      if(!strcmp(argv[1], "tee")) //<path> [buffers]
3324      {
3325          if(argc<=2) return badsyntax("required parameter <path> is missing.");
3326          FILE* teefile = fopen(argv[2],"w");
3327          if(!teefile) return badsyntax("<path> cannot be opened!");
3328          errhead(); fprintf(stderr, "file opened: %s\n", argv[2]);
3329          int num_buffers=100;
3330          if(argc>3) sscanf(argv[3], "%d", &num_buffers);
3331          if(num_buffers<=0) return badsyntax("num_buffers should be > 0");
3332          SET_NONBLOCK(fileno(teefile));
3333          if(!sendbufsize(initialize_buffers())) return -2;
3334          unsigned char* async_tee_buffers = malloc(sizeof(unsigned char)*the_bufsize*num_buffers);
3335          int current_buffer_read_cntr = 0;
3336          int current_buffer_write_cntr = 0;
3337          int current_byte_write_cntr = 0;
3338          for(;;)
3339          {
3340              FEOF_CHECK;
3341              fread(async_tee_buffers+(the_bufsize*current_buffer_read_cntr), sizeof(unsigned char), the_bufsize, stdin);
3342              fwrite(async_tee_buffers+(the_bufsize*current_buffer_read_cntr++), sizeof(unsigned char), the_bufsize, stdout);
3343              if(current_buffer_read_cntr>=num_buffers) current_buffer_read_cntr = 0;
3344              if(current_buffer_read_cntr==current_buffer_write_cntr) { errhead(); fprintf(stderr, "circular buffer overflow (read pointer gone past write pointer)\n"); }
3345              //errhead(); fprintf(stderr, "new fwrites\n");
3346              while(current_buffer_write_cntr!=current_buffer_read_cntr)
3347              {
3348                  int result = fwrite(async_tee_buffers+(the_bufsize*current_buffer_write_cntr)+current_byte_write_cntr, sizeof(unsigned char), the_bufsize-current_byte_write_cntr, teefile);
3349                  if(!result) { errhead(); fprintf(stderr, "\t fwrite tee zero, next turn\n"); break; }
3350                  current_byte_write_cntr += result;
3351                  //errhead(); fprintf(stderr, "\tfwrite tee, current_byte_write_cntr = %d, current_buffer_write_cntr = %d, current_buffer_read_cntr = %d\n", 
3352                  //        current_byte_write_cntr, current_buffer_write_cntr, current_buffer_read_cntr);
3353                  if(current_byte_write_cntr >= the_bufsize) 
3354                  {
3355                      current_byte_write_cntr = 0;
3356                      current_buffer_write_cntr++;
3357                      if(current_buffer_write_cntr>=num_buffers) current_buffer_write_cntr = 0;
3358                  }
3359              }
3360              TRY_YIELD;
3361          }
3362          return 0;
3363      }
3364  
3365      if(!strcmp(argv[1],"shift_addition_fc"))
3366      {
3367          bigbufs=1;
3368  
3369          float starting_phase=0;
3370          float rate;
3371  
3372          int fd;
3373          if(fd=init_fifo(argc,argv))
3374          {
3375              while(!read_fifo_ctl(fd,"%g\n",&rate)) usleep(10000);
3376          }
3377          else
3378          {
3379              if(argc<=2) return badsyntax("need required parameter (rate)");
3380              sscanf(argv[2],"%g",&rate);
3381          }
3382  
3383          if(!sendbufsize(initialize_buffers())) return -2;
3384          for(;;)
3385          {
3386              shift_addition_data_t data=shift_addition_init(rate);
3387              errhead(); fprintf(stderr,"reinitialized to %g\n",rate); 
3388              int remain, current_size;
3389              float* ibufptr;
3390              float* obufptr;
3391              for(;;)
3392              {
3393                  FEOF_CHECK;
3394                  if(!FREAD_R) break;
3395                  remain=the_bufsize;
3396                  ibufptr=input_buffer;
3397                  obufptr=output_buffer;
3398                  while(remain)
3399                  {
3400                      current_size=(remain>1024)?1024:remain;
3401                      starting_phase=shift_addition_fc(ibufptr, (complexf*)obufptr, current_size, data, starting_phase);
3402                      ibufptr+=current_size;
3403                      obufptr+=current_size*2;
3404                      remain-=current_size;
3405                  }
3406                  FWRITE_C;
3407                  if(read_fifo_ctl(fd,"%g\n",&rate)) break;
3408                  TRY_YIELD;
3409              }
3410          }
3411          return 0;
3412      }
3413  
3414      if(!strcmp(argv[1],"fft_fc"))
3415      {
3416          /*
3417          For real FFT, the parameter is the number of output complex bins
3418          instead of the actual FFT size.
3419          Number of input samples used for each FFT is twice the given parameter.
3420          This makes it easier to replace fft_cc by fft_fc in some applications. */
3421          if(argc<=3) return badsyntax("need required parameters (fft_out_size, out_of_every_n_samples)");
3422          int fft_in_size=0, fft_out_size=0;
3423          sscanf(argv[2],"%d",&fft_out_size);
3424          if(log2n(fft_out_size)==-1) return badsyntax("fft_out_size should be power of 2");
3425          fft_in_size = 2*fft_out_size;
3426          int every_n_samples;
3427          sscanf(argv[3],"%d",&every_n_samples);
3428          int benchmark=0;
3429          int octave=0;
3430          window_t window = WINDOW_DEFAULT;
3431          if(argc>=5)
3432          {
3433              window=firdes_get_window_from_string(argv[4]);
3434          }
3435          if(argc>=6)
3436          {
3437              benchmark|=!strcmp("--benchmark",argv[5]);
3438              octave|=!strcmp("--octave",argv[5]);
3439          }
3440          if(argc>=7)
3441          {
3442              benchmark|=!strcmp("--benchmark",argv[6]);
3443              octave|=!strcmp("--octave",argv[6]);
3444          }
3445  
3446          if(!initialize_buffers()) return -2;
3447          sendbufsize(fft_out_size);
3448  
3449          //make FFT plan
3450          float* input=(float*)fft_malloc(sizeof(float)*fft_in_size);
3451          float* windowed=(float*)fft_malloc(sizeof(float)*fft_in_size);
3452          complexf* output=(complexf*)fft_malloc(sizeof(complexf)*fft_out_size);
3453          if(benchmark) { errhead(); fprintf(stderr,"benchmarking..."); }
3454          FFT_PLAN_T* plan=make_fft_r2c(fft_in_size, windowed, output, benchmark);
3455          if(benchmark) fprintf(stderr," done\n");
3456          //if(octave) printf("setenv(\"GNUTERM\",\"X11 noraise\");y=zeros(1,%d);semilogy(y,\"ydatasource\",\"y\");\n",fft_size); // TODO
3457          float *windowt;
3458          windowt = precalculate_window(fft_in_size, window);
3459          for(;;)
3460          {
3461              FEOF_CHECK;
3462              if(every_n_samples>fft_in_size)
3463              {
3464                  fread(input, sizeof(float), fft_in_size, stdin);
3465                  //skipping samples before next FFT (but fseek doesn't work for pipes)
3466                  for(int seek_remain=every_n_samples-fft_in_size;seek_remain>0;seek_remain-=the_bufsize)
3467                  {
3468                      fread(temp_f, sizeof(complexf), MIN_M(the_bufsize,seek_remain), stdin);
3469                  }
3470              }
3471              else
3472              {
3473                  //overlapped FFT
3474                  for(int i=0;i<fft_in_size-every_n_samples;i++) input[i]=input[i+every_n_samples];
3475                  fread(input+fft_in_size-every_n_samples, sizeof(float), every_n_samples, stdin);
3476              }
3477              //apply_window_c(input,windowed,fft_size,window);
3478              apply_precalculated_window_f(input,windowed,fft_in_size,windowt);
3479              fft_execute(plan);
3480              if(octave)
3481              {
3482  #if 0
3483              // TODO
3484                  printf("fftdata=[");
3485                  //we have to swap the two parts of the array to get a valid spectrum
3486                  for(int i=fft_size/2;i<fft_size;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i));
3487                  for(int i=0;i<fft_size/2;i++) printf("(%g)+(%g)*i ",iof(output,i),qof(output,i));
3488                  printf(
3489                      "];\n"
3490                      "y=abs(fftdata);\n"
3491                      "refreshdata;\n"
3492                  );
3493  #endif
3494              }
3495              else fwrite(output, sizeof(complexf), fft_out_size, stdout);
3496              TRY_YIELD;
3497          }
3498      }
3499  /*
3500      if(!strcmp(argv[1],"syncword_search"))
3501      {
3502          if(argc<3) return badsyntax("need required parameter (syncword)");
3503          unsigned long syncword=0UL;
3504          int syncword_length=strlen(argv[2]);
3505          for(int i=0; i<sycword_len;i++)
3506          {
3507              syncword<<=4;
3508              char c=argv[2][i];
3509              unsigned char cval = 0;
3510              if(c<='9'&&c>='0') cval = c-'0';
3511              if(c<='f'&&c>='a') cval = c-'a'+10;
3512              syncword|=cval;
3513          }
3514          errhead(); fprintf("syncword = 0x%0x, syncword_length=%d\n", syncword, syncword_length);
3515          if(argc<4) return badsyntax("need required parameter (bits_after)");
3516          int bits_after = 0;
3517          sscanf(argv[3], &bits_after);
3518          if(bits_after<0) return badsyntax("bits_after should be >0");
3519          unsigned char* syncword_bits = malloc(sizeof(unsigned char)*syncword_length*4);
3520          int k=0;
3521          for(int i=0;i<syncword_length;i++)
3522          {
3523              for(int j=7;j;j--)
3524              {
3525                  syncword_bits[k++]=syncword[i]>>j
3526              }
3527          }
3528          malloc
3529  
3530      }
3531  */
3532      if(!strcmp(argv[1],"pattern_search_u8_u8")) //<values_after> <pattern_values × N>
3533      {
3534          if(argc<3) return badsyntax("need required parameter (values_after)");
3535          int values_after = 0;
3536          sscanf(argv[2], "%d", &values_after);
3537          if(argc<4) return badsyntax("need required parameter (pattern_values × N)");
3538          int pattern_values_length = argc-3;
3539          unsigned* pattern_values = (unsigned*)malloc(sizeof(unsigned)*pattern_values_length);
3540          for(int i=0;i<pattern_values_length;i++)
3541              sscanf(argv[3+i],"%u",pattern_values+i);
3542  
3543          errhead(); fprintf(stderr,"pattern values: ");
3544          for(int i=0;i<pattern_values_length;i++)
3545              fprintf(stderr, "%x ", *(pattern_values+i));
3546          fprintf(stderr,"\n");
3547  
3548          unsigned char* input_buffer = (unsigned char*)malloc(sizeof(unsigned char)*pattern_values_length); //circular buffer
3549          unsigned char* output_buffer = (unsigned char*)malloc(sizeof(unsigned char)*values_after);
3550          int input_index = 0;
3551          int valid_values = 0;
3552          for(;;)
3553          {
3554              FEOF_CHECK;
3555              unsigned char cchar = input_buffer[input_index++]=(unsigned char)fgetc(stdin);
3556              if(valid_values<pattern_values_length) { valid_values++; continue; }
3557              if(input_index>=pattern_values_length) input_index=0;
3558              int match=1;
3559              //fprintf(stderr, "ov1: ");
3560              //for(int i=0;i<pattern_values_length;i++) fprintf(stderr, "%02x ",  input_buffer[i]);
3561              //fprintf(stderr, "\nov2: ");
3562              //for(int i=0;i<pattern_values_length;i++) fprintf(stderr, "%02x ",  pattern_values[i]);
3563              //fprintf(stderr, "\n");
3564  
3565              //fprintf(stderr, "v1: ");
3566              //for(int i=input_index;i<pattern_values_length;i++) fprintf(stderr, "%s%02x ", ((input_buffer[i])?"\x1B[34m":"\x1B[0m"), input_buffer[i]);
3567              //for(int i=0;i<input_index;i++) fprintf(stderr, "%s%02x ", ((input_buffer[i])?"\x1B[34m":"\x1B[0m"), input_buffer[i]);
3568              //fprintf(stderr, "\x1B[0m  %02x\n", cchar);
3569  
3570              //fprintf(stderr, "========\n");
3571              int j=0;
3572              for(int i=input_index;i<pattern_values_length;i++) 
3573              {
3574                  //fprintf(stderr, "%02x ~ %02x\n",  input_buffer[i], pattern_values[j]);
3575                  if(input_buffer[i]!=pattern_values[j++]) { match=0; break;}
3576              }
3577              //fprintf(stderr, "~~~~~~~~\n");
3578              if(input_index!=0 && match) 
3579              {
3580                  for(int i=0;i<input_index;i++) 
3581                  {
3582                      //fprintf(stderr, "%02x ~ %02x\n",  input_buffer[i], pattern_values[j]);
3583                      if(input_buffer[i]!=pattern_values[j++]) { match=0; break;}
3584                  }
3585              }
3586             
3587              //if(match) fprintf(stderr, "j=%d\n", j);
3588              if(match ) 
3589              {
3590                  valid_values = 0;
3591                  //fprintf(stderr,"matched!\n");
3592                  fread(output_buffer, sizeof(unsigned char), values_after, stdin);
3593                  fwrite(output_buffer, sizeof(unsigned char), values_after, stdout);
3594              }
3595              TRY_YIELD;
3596          }
3597      }
3598  
3599      if(!strcmp(argv[1],"none"))
3600      {
3601          return 0;
3602      }
3603  
3604      if(argv[1][0]=='?' && argv[1][1]=='?')
3605      {
3606          char buffer[1000];
3607          snprintf(buffer, 1000-1, "xdg-open https://github.com/simonyiszk/csdr/blob/master/README.md#$(csdr ?%s | head -n1 | awk '{print $1;}')", argv[1]+2);
3608          fprintf(stderr, "csdr ??: %s\n", buffer);
3609          system(buffer);
3610          return 0;
3611      }
3612  
3613      if(argv[1][0]=='?')
3614      {
3615          char buffer[1000];
3616          snprintf(buffer, 1000-1, "csdr 2>&1 | grep -i %s", argv[1]+1);
3617          fprintf(stderr, "csdr ?: %s\n", buffer);
3618          system(buffer);
3619          return 0;
3620      }
3621  
3622      if(argv[1][0]=='=')
3623      {
3624          char buffer[100];
3625          snprintf(buffer, 100-1, "python -c \"import os, sys\nfrom math import *\nprint %s\"", argv[1]+1);
3626          system(buffer);
3627          return 0;
3628      }
3629  
3630      fprintf(stderr,"csdr: function name given in argument 1 (%s) does not exist. Possible causes:\n- You mistyped the commandline.\n- You need to update csdr to a newer version (if available).\n", argv[1]); return -1;
3631  }