ref: 02a0e8ae3cae5d1ef582b5b9ea051fc7f0a3794a
parent: 504e4423e780b4a3e7904e406c43612b96a15702
author: Erik de Castro Lopo <erikd@miles>
date: Mon Nov 1 03:23:47 EST 2004
Last version using cosine based window coefficients.
--- a/FIR-POLY/fir_interp.cc
+++ b/FIR-POLY/fir_interp.cc
@@ -21,6 +21,7 @@
#include <cstdio>
#include <cstdlib>
+#include <unistd.h>
#include <ctime>
#include <cstring>
#include <complex>
@@ -30,7 +31,7 @@
#include "mag_spectrum.hh"
-
+#define UPSAMPLE_RATIO 2.0
#define ARRAY_LEN(x) (sizeof (x) / sizeof ((x) [0]))
/*
@@ -39,35 +40,53 @@
** left_half_offset <= right_half_cycles
*/
-// static int left_half_cycles = 5 ;
-// static int right_half_cycles = 15 ;
+static int left_half_cycles = 6 ;
+static int right_half_cycles = 20 ;
typedef struct
{
- double sinc_time_fudge ;
-
/* Window coefficients (all in range [0, 1]). */
double left_ak [5], right_ak [5] ;
+ double sinc_time_fudge ;
+
} FIR_PARAMS ;
+typedef struct
+{
+ union
+ { FIR_PARAMS fir_params ;
+ double data [20] ;
+ } ;
+
+ unsigned middle, total_len ;
+
+ double sinc [1024] ;
+ double window [1024] ;
+ double filter [1024] ;
+} FIR_INTERP ;
+
static double fir_error (const GMatrix& gm) ;
+static int calc_window (FIR_INTERP *interp, double * error) ;
+static void calc_sinc (FIR_INTERP *interp) ;
+static void calc_filter (FIR_INTERP *interp) ;
+static void oct_save (const FIR_INTERP *interp) ;
+static void randomize_data (FIR_INTERP *interp) ;
+
int
main (void)
-{ static double data [32] ;
+{ FIR_INTERP interp ;
GMatrix gm_start ;
double error ;
- int k, param_count ;
-
+ int param_count ;
+
param_count = sizeof (FIR_PARAMS) / sizeof (double) ;
- srandom (time (NULL)) ;
- for (k = 0 ; k < param_count ; k++)
- data [k] = 3.0 * ((1.0 * random ()) / INT_MAX - 0.5) ;
+ randomize_data (&interp) ;
- gm_start = GMatrix (param_count, 1, data) ;
+ gm_start = GMatrix (param_count, 1, interp.data) ;
fir_error (gm_start) ;
@@ -85,20 +104,216 @@
static double
fir_error (const GMatrix& gm)
-{ FIR_PARAMS params ;
+{ static FIR_INTERP interp ;
double error = 0.0 ;
unsigned param_count ;
-
-
- param_count = sizeof (params) / sizeof (double) ;
- if (gm.GetData (param_count, (double*) ¶ms) != param_count)
- { printf ("\n\nError : GetData should return 2.\n") ;
+ memset (&interp, 0, sizeof (interp)) ;
+
+ param_count = sizeof (FIR_PARAMS) / sizeof (double) ;
+
+ if (ARRAY_LEN (interp.data) < param_count)
+ { printf ("\n\nError : ARRAY_LEN (interp.data) < param_count.\n") ;
exit (1) ;
} ;
+ if (gm.GetData (param_count, interp.data) != param_count)
+ { printf ("\n\nError : GetData should return %d.\n", param_count) ;
+ exit (1) ;
+ } ;
+
+ /* Eval error in sinc_time_fudge. */
+ if (interp.fir_params.sinc_time_fudge < 1.0)
+ return 1e30 * (fabs (interp.fir_params.sinc_time_fudge - 1.0)) ;
+
+ if (interp.fir_params.sinc_time_fudge > 1.25)
+ return 1e30 * (fabs (interp.fir_params.sinc_time_fudge - 1.25)) ;
+
+ interp.middle = lrint (floor (left_half_cycles * UPSAMPLE_RATIO / interp.fir_params.sinc_time_fudge)) ;
+ interp.total_len = interp.middle + lrint (floor (right_half_cycles * UPSAMPLE_RATIO / interp.fir_params.sinc_time_fudge)) ;
+
+ if (interp.total_len > ARRAY_LEN (interp.sinc))
+ { printf ("\n\nError : interp.total_len > ARRAY_LEN (interp.sinc).\n") ;
+ exit (1) ;
+ } ;
+
+ if (calc_window (&interp, &error))
+ return error ;
+
+ calc_sinc (&interp) ;
+
+ calc_filter (&interp) ;
+
+ oct_save (&interp) ;
+ printf ("%s %d\n", __func__, __LINE__) ;
+ exit (1) ;
+
return error ;
} /* fir_error */
+
+static int
+calc_window (FIR_INTERP *interp, double * returned_error)
+{ unsigned k, coeff ;
+ double x, sum, error ;
+
+ /* Check left zeroth coefficient. */
+ if (interp->fir_params.left_ak [0] < 0.0)
+ { *returned_error = 1e20 * fabs (interp->fir_params.left_ak [0]) ;
+ return 1 ;
+ } ;
+
+ if (interp->fir_params.left_ak [0] > 0.5)
+ { *returned_error = 1e20 * (interp->fir_params.left_ak [0] - 0.5) ;
+ return 1 ;
+ } ;
+
+ /* Check right zeroth coefficient. */
+ if (interp->fir_params.right_ak [0] < 0.0)
+ { *returned_error = 1e20 * fabs (interp->fir_params.right_ak [0]) ;
+ return 1 ;
+ } ;
+
+ if (interp->fir_params.right_ak [0] > 0.5)
+ { *returned_error = 1e20 * (interp->fir_params.right_ak [0] - 0.5) ;
+ return 1 ;
+ } ;
+
+ /* Massage left coefficients. */
+ sum = 0.0 ;
+ for (k = 0 ; k < ARRAY_LEN (interp->fir_params.left_ak) ; k++)
+ { if (sum > 1.0)
+ interp->fir_params.left_ak [k] = 0.0 ;
+ interp->fir_params.left_ak [k] = fabs (interp->fir_params.left_ak [k]) ;
+ if (sum + interp->fir_params.left_ak [k] > 1.0)
+ interp->fir_params.left_ak [k] = 1.0 - sum ;
+ sum += interp->fir_params.left_ak [k] ;
+ } ;
+
+ /* Massage right coefficients. */
+ sum = 0.0 ;
+ for (k = 0 ; k < ARRAY_LEN (interp->fir_params.right_ak) ; k++)
+ { if (sum > 1.0)
+ interp->fir_params.right_ak [k] = 0.0 ;
+ interp->fir_params.right_ak [k] = fabs (interp->fir_params.right_ak [k]) ;
+ if (sum + interp->fir_params.right_ak [k] > 1.0)
+ interp->fir_params.right_ak [k] = 1.0 - sum ;
+ sum += interp->fir_params.right_ak [k] ;
+ } ;
+
+ /* Generate left side of window. */
+ error = 0.0 ;
+ for (k = 0 ; k <= interp->middle ; k++)
+ { interp->window [k] = interp->fir_params.left_ak [0] ;
+ x = M_PI * (interp->middle - k) / (1.0 * interp->middle) ;
+ for (coeff = 1 ; coeff < ARRAY_LEN (interp->fir_params.left_ak) ; coeff ++)
+ interp->window [k] += interp->fir_params.left_ak [coeff] * cos (coeff * x) ;
+ if (fabs (interp->window [k] - 0.5) > 0.5)
+ error = fabs (interp->window [k] - 0.5) ;
+ } ;
+
+ if (error > 0.0)
+ { *returned_error = 1e20 * error ;
+ return 1 ;
+ } ;
+
+ if (interp->window [0] > 0.25)
+ { *returned_error = 1e18 * interp->window [0] ;
+ return 1 ;
+ } ;
+
+
+// for (k = interp->middle + 1 ; k < interp->total_len ; k++)
+
+ return 0 ;
+} /* calc_window */
+
+static void
+calc_sinc (FIR_INTERP *interp)
+{ unsigned k ;
+ double x ;
+
+ for (k = 0 ; k < interp->middle ; k++)
+ { x = M_PI * (interp->middle - k) * interp->fir_params.sinc_time_fudge / UPSAMPLE_RATIO ;
+ interp->sinc [k] = sin (x) / x ;
+ } ;
+ interp->sinc [interp->middle] = 1.0 ;
+
+ for (k = interp->middle + 1 ; k < interp->total_len ; k++)
+ { x = M_PI * (k - interp->middle) * interp->fir_params.sinc_time_fudge / UPSAMPLE_RATIO ;
+ interp->sinc [k] = sin (x) / x ;
+ } ;
+
+} /* calc_sinc */
+
+static void
+calc_filter (FIR_INTERP *interp)
+{ unsigned k ;
+
+ for (k = 0 ; k < interp->total_len ; k++)
+ interp->filter [k] = interp->sinc [k] * interp->window [k] ;
+
+} /* calc_sinc */
+
+static void
+oct_save (const FIR_INTERP *interp)
+{ const char * filename = "a.mat" ;
+ FILE * file ;
+ unsigned k ;
+
+ unlink (filename) ;
+
+ if ((file = fopen (filename, "w")) == NULL)
+ { printf ("\nError : fopen failed.\n") ;
+ exit (1) ;
+ } ;
+
+ fprintf (file, "# Not created by Octave\n") ;
+
+ fprintf (file, "# name: sinc_time_fudge\n") ;
+ fprintf (file, "# type: scalar\n%16.14f\n", interp->fir_params.sinc_time_fudge) ;
+
+ fprintf (file, "# name: middle\n") ;
+ fprintf (file, "# type: scalar\n%d\n", interp->middle) ;
+
+ fprintf (file, "# name: total_len\n") ;
+ fprintf (file, "# type: scalar\n%d\n", interp->total_len) ;
+
+ fprintf (file, "# name: sinc\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", interp->total_len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < interp->total_len ; k++)
+ fprintf (file, "% f\n", interp->sinc [k]) ;
+
+ fprintf (file, "# name: window\n") ;
+ fprintf (file, "# type: matrix\n") ;
+ fprintf (file, "# rows: %d\n", interp->total_len) ;
+ fprintf (file, "# columns: 1\n") ;
+
+ for (k = 0 ; k < interp->total_len ; k++)
+ fprintf (file, "% f\n", interp->window [k]) ;
+
+ fclose (file) ;
+} /* oct_save */
+
+static void
+randomize_data (FIR_INTERP *interp)
+{ FILE * file ;
+ unsigned k, param_count, seed ;
+
+ file = fopen ("/dev/urandom", "r") ;
+ fread (&seed, 1, sizeof (seed), file) ;
+ fclose (file) ;
+
+ srandom (seed) ;
+
+ param_count = sizeof (FIR_PARAMS) / sizeof (double) ;
+
+ for (k = 0 ; k < param_count ; k++)
+ interp->data [k] = 3.0 * ((1.0 * random ()) / INT_MAX - 0.5) ;
+
+} /* randomize_data */
/*
** Do not edit or modify anything in this comment block.