//
//	Downsample a file from one frequency to another.  Uses a
//	LpBu10 filter, with a cutoff at 33% of the target sampling
//	frequency.  This gives some fold-back of higher frequencies,
//	but only about 0.1% at the level of 33% of the target rate.
//

#include <stdio.h>
#include <string.h>
#include <math.h>
#include "fidlib.h"

double lowpass_step(double *coef, double *buf, double val);

void 
usage() {
   fprintf(stderr, "Usage: downsample <input-rate> <downsamping-ratio>\n"
	   "e.g. use: downsample 44100 22 <in.raw >out.raw\n"
	   "to downsample a 16-bit stereo raw file from 44100 to 2004.55Hz\n"
	   );
   exit(1);
}

//
//	Main routine
//

int 
main(int ac, char **av) {
   short data[2];
   double coef[11];
   double dsbuf[2][10];
   double left, right;
   double irate, orate;
   int dsrat;
   char dmy;
   int cnt;

   ac--; av++;
   if (ac != 2) usage();

   if (1 != sscanf(av[0], "%lf %c", &irate, &dmy)) usage();
   if (1 != sscanf(av[1], "%d %c", &dsrat, &dmy)) usage();
   if (dsrat < 2) usage();
   orate= irate / dsrat;

   // Init filter
   coef[0]= fid_design_coef(coef+1, 10, "LpBu10", irate, orate / 3, 0, 0);
   memset(dsbuf, 0, sizeof(dsbuf));

   cnt= dsrat;
   while (1) {
      if (2 != fread(data, 2, sizeof(short), stdin)) break;
      left= lowpass_step(coef, dsbuf[0], data[0] * (1.0/32768.0));
      right= lowpass_step(coef, dsbuf[1], data[1] * (1.0/32768.0));

      if (--cnt > 0) continue;
      cnt= dsrat;

      data[0]= (int)(32768 * left);
      data[1]= (int)(32768 * right);

      if (2 != fwrite(data, 2, sizeof(short), stdout)) {
	 fprintf(stderr, "Write error\n"); 
	 break;
      }
   }

   return 0;
}

// Generated by Fiview 0.9.1 <http://uazu.net/fiview/>.  
// All generated example code below is in the public domain.
// Filter 1
// File: -i #1
// Guessed type: low-pass
//
// Frequency-response:
//   Peak gain: 1
//   Guessed 100% gain: 1
//   Regions between 50% (~-3dB) points:
//     0Hz -> 704.603Hz  (width 704.603Hz)
//
// Time-response:
//   Sampling rate is 44100Hz
//   90% complete after 184 samples (0.00417234s)
//   95% complete after 226 samples (0.00512472s)
//   99% complete after 332 samples (0.00752834s)
//   99.9% complete after 491 samples (0.0111338s)
//   99.99% complete after 649 samples (0.0147166s)
//   Impulse response max deviation is at 77 samples (0.00174603s)
//   Impulse response ranges between -0.011811 and 0.0307124
//
// Original filter:
//   x 4.36177017209651e-14
//   / 1 -1.96185441465406 0.970746592664127
//   x 1 2 1
//   / 1 -1.90874985629586 0.917401335922523
//   x 1 2 1
//   / 1 -1.86578842529115 0.87424518063593
//   x 1 2 1
//   / 1 -1.83576856334409 0.844089252549467
//   x 1 2 1
//   / 1 -1.82037037125029 0.828621267578017
//   x 1 2 1 (LpBu10/667)
//
// Filter descriptions:
//   LpBu10/667 == Lowpass Butterworth filter, order 10, -3dB frequency 667
//


// Example code for generating any of this class of filters at run-time
double
lowpass_step(double *coef, double *buf, double val) {
   register double tmp, fir, iir;
   tmp= buf[0]; memmove(buf, buf+1, 9*sizeof(double));
   iir= val * coef[0];
   iir -= coef[1]*tmp; fir= tmp;
   iir -= coef[2]*buf[0]; fir += buf[0]+buf[0];
   fir += iir;
   tmp= buf[1]; buf[1]= iir; val= fir;
   iir= val;
   iir -= coef[3]*tmp; fir= tmp;
   iir -= coef[4]*buf[2]; fir += buf[2]+buf[2];
   fir += iir;
   tmp= buf[3]; buf[3]= iir; val= fir;
   iir= val;
   iir -= coef[5]*tmp; fir= tmp;
   iir -= coef[6]*buf[4]; fir += buf[4]+buf[4];
   fir += iir;
   tmp= buf[5]; buf[5]= iir; val= fir;
   iir= val;
   iir -= coef[7]*tmp; fir= tmp;
   iir -= coef[8]*buf[6]; fir += buf[6]+buf[6];
   fir += iir;
   tmp= buf[7]; buf[7]= iir; val= fir;
   iir= val;
   iir -= coef[9]*tmp; fir= tmp;
   iir -= coef[10]*buf[8]; fir += buf[8]+buf[8];
   fir += iir;
   buf[9]= iir; val= fir;
   return val;
}


// END //
