r4053 - in trunk/bse: . tests
- From: timj svn gnome org
- To: svn-commits-list gnome org
- Subject: r4053 - in trunk/bse: . tests
- Date: Thu, 2 Nov 2006 16:45:28 -0500 (EST)
Author: timj
Date: 2006-11-02 16:45:13 -0500 (Thu, 02 Nov 2006)
New Revision: 4053
Modified:
trunk/bse/ChangeLog
trunk/bse/bsefilter-ellf.c
trunk/bse/bsefilter.cc
trunk/bse/bsemath.c
trunk/bse/tests/filtertest.cc
Log:
Thu Nov 2 22:44:16 2006 Tim Janik <timj gtk org>
* bsemath.c: temporary fix against ring buffer overflow.
* bsefilter-ellf.c: replaced overly verbose debugging function
implementation by simple printf like macros. moved ellf compat
constant definitions.
* bsefilter.cc: cosmetic changes to bse_iir_filter_request_string().
* tests/filtertest.cc: compare filter zero/pole coefficients
instead of filter transfer function coefficients which are useless
for high order filters. zero/pole pairs for comparsion are
determined through nearest-neighbour searches.
use TABORT_HANDLER() to hook up print_filter_on_abort(), to print
out mismatching filters when tests fail. use T*_CMP() test macros
for more informative printouts. extended generic filter test to
cover more filter properties.
added predesigned filters where ellf miscalculates gain.
Modified: trunk/bse/ChangeLog
===================================================================
--- trunk/bse/ChangeLog 2006-11-02 21:31:58 UTC (rev 4052)
+++ trunk/bse/ChangeLog 2006-11-02 21:45:13 UTC (rev 4053)
@@ -1,3 +1,23 @@
+Thu Nov 2 22:44:16 2006 Tim Janik <timj gtk org>
+
+ * bsemath.c: temporary fix against ring buffer overflow.
+
+ * bsefilter-ellf.c: replaced overly verbose debugging function
+ implementation by simple printf like macros. moved ellf compat
+ constant definitions.
+
+ * bsefilter.cc: cosmetic changes to bse_iir_filter_request_string().
+
+ * tests/filtertest.cc: compare filter zero/pole coefficients
+ instead of filter transfer function coefficients which are useless
+ for high order filters. zero/pole pairs for comparsion are
+ determined through nearest-neighbour searches.
+ use TABORT_HANDLER() to hook up print_filter_on_abort(), to print
+ out mismatching filters when tests fail. use T*_CMP() test macros
+ for more informative printouts. extended generic filter test to
+ cover more filter properties.
+ added predesigned filters where ellf miscalculates gain.
+
Tue Oct 31 13:52:17 2006 Stefan Westerfeld <stefan space twc de>
* tests/filtertest.cc: Raise coefficient comparision epsilon ceps
Modified: trunk/bse/bsefilter-ellf.c
===================================================================
--- trunk/bse/bsefilter-ellf.c 2006-11-02 21:31:58 UTC (rev 4052)
+++ trunk/bse/bsefilter-ellf.c 2006-11-02 21:45:13 UTC (rev 4053)
@@ -118,28 +118,7 @@
double zd[BSE_IIR_CARRAY_SIZE]; /* denominator coefficients [order+1] */
} EllfDesignState;
-static void __attribute__ ((__format__ (__printf__, 1, 2)))
-VERBOSE (const char *format,
- ...)
-{
- char buffer[4096];
- va_list args;
- va_start (args, format);
- vsnprintf (buffer, sizeof (buffer), format, args);
- va_end (args);
- printf ("# %s", buffer);
- fflush (stdout);
-}
-
-#define EVERBOSE VERBOSE
-//#define EVERBOSE(...) do{}while (0)
-
-static const char* ellf_filter_design (const BseIIRFilterRequest *ifr,
- EllfDesignState *ds);
-
-
-#ifndef ELLF_BEHAVIOR
-
+#if 0 // precision
//#include "bseieee754.h"
#define PI (3.141592653589793238462643383279502884197) // pi
#define BSE_PI_DIV_2 (1.570796326794896619231321691639751442099) // pi/2
@@ -155,15 +134,51 @@
#define PIO2 (BSE_PI_DIV_2) /* pi/2 */
#define MAXNUM (BSE_DOUBLE_MAX_NORMAL) /* 2**1024*(1-MACHEP) */
+#else
+
+static double DECIBELL_FACTOR = -1;
+static void
+init_constants (void)
+{
+ DECIBELL_FACTOR = 10.0 / log (10.0);
+}
+static const double MAXNUM = 1.79769313486231570815E308; /* 2**1024*(1-MACHEP) */
+#undef PI
+static const double PI = 3.14159265358979323846; /* pi */
+static const double PIO2 = 1.57079632679489661923; /* pi/2 */
+static const double MACHEP = 1.11022302462515654042E-16; /* 2**-53 */
+#endif
+
+
+
+#if 0
+#define error_printf(...) fprintf (stderr, __VA_ARGS__)
+#define ellf_debugf(...) fprintf (stderr, __VA_ARGS__)
+#define ellf_outputf(...) fprintf (stdout, __VA_ARGS__)
+#define ellf_inputf(...) fprintf (stdout, __VA_ARGS__)
+#else
+#define error_printf(...) while (0) { printf (__VA_ARGS__); }
+#define ellf_debugf(...) while (0) { printf (__VA_ARGS__); }
+#define ellf_outputf(...) while (0) { printf (__VA_ARGS__); }
+#define ellf_inputf(...) while (0) { printf (__VA_ARGS__); }
+#endif
+
+static const char* ellf_filter_design (const BseIIRFilterRequest *ifr,
+ EllfDesignState *ds);
+
+
+#ifndef ELLF_BEHAVIOR
+
bool
_bse_filter_design_ellf (const BseIIRFilterRequest *ifr,
BseIIRFilterDesign *fid)
{
+ init_constants();
EllfDesignState ds = { 0, };
const char *errmsg = ellf_filter_design (ifr, &ds);
fflush (stdout);
fflush (stderr);
- // VERBOSE ("DEBUG: %.20g %.20g %.20g %.20g %.20g\n", a, cos(a), cang, ds->cgam, 0.);
+ // ellf_debugf ("DEBUG: %.20g %.20g %.20g %.20g %.20g\n", a, cos(a), cang, ds->cgam, 0.);
if (errmsg)
return false;
fid->order = ds.n_solved_poles;
@@ -191,22 +206,10 @@
#else
-static double DECIBELL_FACTOR = -1;
-static void
-init_constants (void)
-{
- DECIBELL_FACTOR = 10.0 / log (10.0);
-}
-static const double MAXNUM = 1.79769313486231570815E308; /* 2**1024*(1-MACHEP) */
-static const double PI = 3.14159265358979323846; /* pi */
-static const double PIO2 = 1.57079632679489661923; /* pi/2 */
-static const double MACHEP = 1.11022302462515654042E-16; /* 2**-53 */
-
-
static double
my_getnum (const char *text)
{
- printf ("%s ? ", text);
+ ellf_inputf ("%s ? ", text);
char s[4096];
if (!fgets (s, sizeof (s), stdin))
exit (0);
@@ -240,14 +243,14 @@
ifr.passband_edge2 = my_getnum ("passband_edge2");
if (ifr.kind == BSE_IIR_FILTER_ELLIPTIC)
ifr.stopband_db = ifr.stopband_edge = my_getnum ("stopband_edge or stopband_db");
- printf ("\n");
+ ellf_inputf ("\n");
const char *errmsg = ellf_filter_design (&ifr, &ds);
fflush (stdout);
fflush (stderr);
- // VERBOSE ("DEBUG: %.20g %.20g %.20g %.20g %.20g\n", a, cos(a), cang, ds->cgam, 0.);
+ // ellf_debugf ("DEBUG: %.20g %.20g %.20g %.20g %.20g\n", a, cos(a), cang, ds->cgam, 0.);
if (errmsg)
{
- fprintf (stderr, "Invalid specification: %s\n", errmsg);
+ error_printf (stderr, "Invalid specification: %s\n", errmsg);
fflush (stderr);
return 1;
}
@@ -397,7 +400,7 @@
* which is supposed to be the name of the
* function in which the error occurred:
*/
- printf ("\n%s ", name); // FIXME
+ error_printf ("\n%s ", name); // FIXME
/* Set global error message word */
math_global_error = code;
@@ -407,7 +410,7 @@
*/
if ((code <= 0) || (code >= 7))
code = 0;
- printf ("%s error\n", ermsg[code]);
+ error_printf ("%s error\n", ermsg[code]);
/* Return to calling
* program
@@ -1094,11 +1097,11 @@
zgain = 1.0;
else
zgain = ds->denominator_accu / (ds->numerator_accu * ds->gain_scale);
- VERBOSE ("# constant mygain factor %23.13E\n", zgain); // BSE info
- VERBOSE ("# z plane Denominator Numerator\n"); // BSE info
+ ellf_outputf ("# constant mygain factor %23.13E\n", zgain); // BSE info
+ ellf_outputf ("# z plane Denominator Numerator\n"); // BSE info
int j;
for (j = 0; j <= ds->n_solved_poles; j++)
- VERBOSE ("%2d %17.9E %17.9E\n", j, ds->zd[j], ds->zn[j] * zgain); // BSE info
+ ellf_outputf ("# %2d %17.9E %17.9E\n", j, ds->zd[j], ds->zn[j] * zgain); // BSE info
}
@@ -1110,37 +1113,37 @@
double m = k * k;
ds->elliptic_Kk = ellpk (1.0 - m);
ds->elliptic_Kpk = ellpk (m);
- EVERBOSE ("check: k=%.20g m=%.20g Kk=%.20g Kpk=%.20g\n", k, m, ds->elliptic_Kk, ds->elliptic_Kpk); // BSE info
+ ellf_debugf ("check: k=%.20g m=%.20g Kk=%.20g Kpk=%.20g\n", k, m, ds->elliptic_Kk, ds->elliptic_Kpk); // BSE info
double q = exp (-PI * ifr->order * ds->elliptic_Kpk / ds->elliptic_Kk); /* the nome of k1 */
double m1 = jacobi_theta_by_nome (q); /* see below */
/* Note m1 = ds->ripple_epsilon / sqrt(A*A - 1.0) */
double a = ds->ripple_epsilon / m1;
a = a * a + 1;
a = 10.0 * log (a) / log (10.0);
- printf ("dbdown %.9E\n", a);
+ ellf_debugf ("dbdown %.9E\n", a);
a = 180.0 * asin (k) / PI;
double b = 1.0 / (1.0 + ds->ripple_epsilon * ds->ripple_epsilon);
b = sqrt (1.0 - b);
- printf ("theta=%.9E, rho=%.9E\n", a, b);
+ ellf_debugf ("theta=%.9E, rho=%.9E\n", a, b);
m1 *= m1;
double m1p = 1.0 - m1;
double Kk1 = ellpk (m1p);
double Kpk1 = ellpk (m1);
double r = Kpk1 * ds->elliptic_Kk / (Kk1 * ds->elliptic_Kpk);
- printf ("consistency check: n= %.14E\n", r);
- EVERBOSE ("consistency check: r=%.20g Kpk1=%.20g Kk1=%.20g m1=%.20g m1p=%.20g\n", r, Kpk1, Kk1, m1, m1p); // BSE info
+ ellf_debugf ("consistency check: n= %.14E\n", r);
+ ellf_debugf ("consistency check: r=%.20g Kpk1=%.20g Kk1=%.20g m1=%.20g m1p=%.20g\n", r, Kpk1, Kk1, m1, m1p); // BSE info
/* -1
* sn j/ds->ripple_epsilon\m = j ellik(atan(1/ds->ripple_epsilon), m)
*/
b = 1.0 / ds->ripple_epsilon;
ds->elliptic_phi = atan (b);
double u = ellik (ds->elliptic_phi, m1p);
- EVERBOSE ("phi=%.20g m=%.20g u=%.20g\n", ds->elliptic_phi, m1p, u);
+ ellf_debugf ("phi=%.20g m=%.20g u=%.20g\n", ds->elliptic_phi, m1p, u);
/* consistency check on inverse sn */
double sn, cn, dn;
ellpj (u, m1p, &sn, &cn, &dn, &ds->elliptic_phi);
a = sn / cn;
- EVERBOSE ("consistency check: sn/cn = %.20g = %.20g = 1/ripple\n", a, b);
+ ellf_debugf ("consistency check: sn/cn = %.20g = %.20g = 1/ripple\n", a, b);
ds->elliptic_k = k;
ds->elliptic_u = u * ds->elliptic_Kk / (ifr->order * Kk1); /* or, u = u * Kpk / Kpk1 */
ds->elliptic_m = m;
@@ -1213,9 +1216,9 @@
/* sqrt(1 + 1/ds->ripple_epsilon^2) + 1/ds->ripple_epsilon = {sqrt(1 + ds->ripple_epsilon^2) + 1} / ds->ripple_epsilon
*/
ds->chebyshev_phi = (ds->chebyshev_phi + 1.0) / ds->ripple_epsilon;
- EVERBOSE ("Chebychev: phi-before=%.20g ripple=%.20g\n", ds->chebyshev_phi, ds->ripple_epsilon); // BSE info
+ ellf_debugf ("Chebychev: phi-before=%.20g ripple=%.20g\n", ds->chebyshev_phi, ds->ripple_epsilon); // BSE info
ds->chebyshev_phi = pow (ds->chebyshev_phi, 1.0 / ifr->order); /* raise to the 1/n power */
- EVERBOSE ("Chebychev: phi-raised=%.20g rn=%.20g\n", ds->chebyshev_phi, ifr->order * 1.0); // BSE info
+ ellf_debugf ("Chebychev: phi-raised=%.20g rn=%.20g\n", ds->chebyshev_phi, ifr->order * 1.0); // BSE info
double b = 0.5 * (ds->chebyshev_phi + 1.0 / ds->chebyshev_phi); /* y coordinates are on this circle */
double a = 0.5 * (ds->chebyshev_phi - 1.0 / ds->chebyshev_phi); /* x coordinates are on this circle */
double m;
@@ -1312,7 +1315,7 @@
}
}
}
- printf ("s plane poles:\n");
+ ellf_outputf ("s plane poles:\n");
j = 0;
for (i = 0; i < ds->n_poles + ds->n_zeros; i++)
{
@@ -1320,9 +1323,9 @@
++j;
double b = spz[j];
++j;
- printf ("%.9E %.9E\n", a, b);
+ ellf_outputf ("%.9E %.9E\n", a, b);
if (i == ds->n_poles - 1)
- printf ("s plane zeros:\n");
+ ellf_outputf ("s plane zeros:\n");
}
return 0;
}
@@ -1481,14 +1484,14 @@
{
if (ifr->type != BSE_IIR_FILTER_HIGH_PASS)
{
- printf ("adding zero at Nyquist frequency\n");
+ ellf_debugf ("adding zero at Nyquist frequency\n");
ds->z_counter += 1;
ds->zcpz[ds->z_counter].r = -1.0; /* zero at Nyquist frequency */
ds->zcpz[ds->z_counter].i = 0.0;
}
if (ifr->type == BSE_IIR_FILTER_BAND_PASS || ifr->type == BSE_IIR_FILTER_HIGH_PASS)
{
- printf ("adding zero at 0 Hz\n");
+ ellf_debugf ("adding zero at 0 Hz\n");
ds->z_counter += 1;
ds->zcpz[ds->z_counter].r = 1.0; /* zero at 0 Hz */
ds->zcpz[ds->z_counter].i = 0.0;
@@ -1510,7 +1513,7 @@
}
}
}
- printf ("order = %d\n", ds->n_solved_poles);
+ ellf_outputf ("order = %d\n", ds->n_solved_poles);
/* Expand the poles and zeros into numerator and
* denominator polynomials
@@ -1605,7 +1608,7 @@
a = -x;
b = 0.0;
}
- printf ("q. f.\nz**2 %23.13E\nz**1 %23.13E\n", b, a);
+ ellf_outputf ("q. f.\nz**2 %23.13E\nz**1 %23.13E\n", b, a);
if (b != 0.0)
{
/* resonant frequency */
@@ -1639,7 +1642,7 @@
else
g = MAXNUM;
}
- printf ("f0 %16.8E gain %12.4E DC gain %12.4E\n\n", f, g, g0);
+ ellf_outputf ("f0 %16.8E gain %12.4E DC gain %12.4E\n\n", f, g, g0);
return 0;
}
@@ -1651,34 +1654,34 @@
ds->gain = ds->denominator_accu / (ds->numerator_accu * ds->gain_scale);
if ((ifr->kind == BSE_IIR_FILTER_BUTTERWORTH || ifr->kind == BSE_IIR_FILTER_CHEBYSHEV1) && ds->numerator_accu == 0)
ds->gain = 1.0;
- printf ("constant gain factor %23.13E\n", ds->gain);
+ ellf_outputf ("constant gain factor %23.13E\n", ds->gain);
for (j = 0; j <= ds->n_solved_poles; j++)
ds->zn[j] = ds->gain * ds->zn[j];
- printf ("z plane Denominator Numerator\n");
+ ellf_outputf ("z plane Denominator Numerator\n");
for (j = 0; j <= ds->n_solved_poles; j++)
{
- printf ("%2d %17.9E %17.9E\n", j, ds->zd[j], ds->zn[j]);
+ ellf_outputf ("%2d %17.9E %17.9E\n", j, ds->zd[j], ds->zn[j]);
}
/* I /think/ at this point the polynomial is factorized in 2nd order filters,
* so that it can be implemented without stability problems -- stw
*/
- printf ("poles and zeros with corresponding quadratic factors\n");
+ ellf_outputf ("poles and zeros with corresponding quadratic factors\n");
for (j = 0; j < ds->n_solved_poles; j++)
{
double a = ds->zcpz[j].r;
double b = ds->zcpz[j].i;
if (b >= 0.0)
{
- printf ("pole %23.13E %23.13E\n", a, b);
+ ellf_outputf ("pole %23.13E %23.13E\n", a, b);
print_quadratic_factors (ifr, ds, a, b, true);
}
a = ds->zcpz[ds->n_solved_poles + j].r;
b = ds->zcpz[ds->n_solved_poles + j].i;
if (b >= 0.0)
{
- printf ("zero %23.13E %23.13E\n", a, b);
+ ellf_outputf ("zero %23.13E %23.13E\n", a, b);
print_quadratic_factors (ifr, ds, a, b, false);
}
}
@@ -1732,7 +1735,7 @@
r = -999.99;
else
r = 2.0 * DECIBELL_FACTOR * log (r);
- printf ("%10.1f %10.2f\n", f, r);
+ ellf_debugf ("%10.1f %10.2f\n", f, r);
// f = f + 0.05 * ds->nyquist_frequency;
}
}
@@ -1832,7 +1835,7 @@
if (ifr->kind == BSE_IIR_FILTER_BUTTERWORTH || ifr->kind == BSE_IIR_FILTER_CHEBYSHEV1)
{
ds->wc = ds->tan_angle_frequency;
- /*printf("cos(1/2 (Whigh-Wlow) T) = %.5e, wc = %.5e\n", cang, ds->wc);*/
+ /*ellf_debugf("cos(1/2 (Whigh-Wlow) T) = %.5e, wc = %.5e\n", cang, ds->wc);*/
}
if (ifr->kind == BSE_IIR_FILTER_ELLIPTIC)
@@ -1926,8 +1929,8 @@
double tmp_y = i == 1 ? tmp_y0 : tmp_y1;
ds->zd[i] = atan (ds->tan_angle_frequency * tmp_y) * ifr->sampling_frequency / PI ;
}
- printf ("pass band %.9E\n", ds->zd[1]);
- printf ("stop band %.9E\n", ds->zd[2]);
+ ellf_debugf ("pass band %.9E\n", ds->zd[1]);
+ ellf_debugf ("stop band %.9E\n", ds->zd[2]);
}
else
{
@@ -1942,8 +1945,8 @@
ds->zd[i] = (q + b) * ds->nyquist_frequency / PI;
ds->zn[i] = (q - b) * ds->nyquist_frequency / PI;
}
- printf ("pass band %.9E %.9E\n", ds->zn[1], ds->zd[1]);
- printf ("stop band %.9E %.9E\n", ds->zn[2], ds->zd[2]);
+ ellf_debugf ("pass band %.9E %.9E\n", ds->zn[1], ds->zd[1]);
+ ellf_debugf ("stop band %.9E %.9E\n", ds->zn[2], ds->zd[2]);
}
ds->wc = 1.0;
find_elliptic_locations_in_lambda_plane (ifr, ds); /* find locations in lambda plane */
@@ -1980,12 +1983,12 @@
/* ds->chebyshev_band_cbp = (ds->cgam - cos (a)) / sin (a); */
ds->gain_scale = 1.0;
}
-
- EVERBOSE ("State: gain_scale=%.20g ripple_epsilon=%.20g nyquist_frequency=%.20g " // BSE info
- "tan_angle_frequency=%.20g stopband_edge=%.20g wc=%.20g wr=%.20g cgam=%.20g\n",
- ds->gain_scale, ds->ripple_epsilon, ds->nyquist_frequency,
- ds->tan_angle_frequency, ds->stopband_edge, ds->wc, ds->wr, ds->cgam);
-
+
+ ellf_debugf ("State: gain_scale=%.20g ripple_epsilon=%.20g nyquist_frequency=%.20g " // BSE info
+ "tan_angle_frequency=%.20g stopband_edge=%.20g wc=%.20g wr=%.20g cgam=%.20g\n",
+ ds->gain_scale, ds->ripple_epsilon, ds->nyquist_frequency,
+ ds->tan_angle_frequency, ds->stopband_edge, ds->wc, ds->wr, ds->cgam);
+
find_s_plane_poles_and_zeros (ifr, ds); /* find s plane poles and zeros */
if ((ifr->type == BSE_IIR_FILTER_BAND_PASS || ifr->type == BSE_IIR_FILTER_BAND_STOP) && 4 * ifr->order + 2 > BSE_IIR_CARRAY_SIZE)
@@ -1994,7 +1997,7 @@
convert_s_plane_to_z_plane (ifr, ds); /* convert s plane to z plane */
// volatile_sink ("x");
z_plane_zeros_poles_to_numerator_denomerator (ifr, ds);
- EVERBOSE ("an=%.20g pn=%.20g scale=%.20g\n", ds->denominator_accu, ds->numerator_accu, ds->gain_scale); // BSE info
+ ellf_debugf ("an=%.20g pn=%.20g scale=%.20g\n", ds->denominator_accu, ds->numerator_accu, ds->gain_scale); // BSE info
print_z_fraction_before_zplnc (ifr, ds);
gainscale_and_print_deno_nume_zeros2_poles2 (ifr, ds);
print_filter_table (ifr, ds); /* tabulate transfer function */
Modified: trunk/bse/bsefilter.cc
===================================================================
--- trunk/bse/bsefilter.cc 2006-11-02 21:31:58 UTC (rev 4052)
+++ trunk/bse/bsefilter.cc 2006-11-02 21:45:13 UTC (rev 4053)
@@ -59,15 +59,15 @@
s += bse_iir_filter_type_string (ifr->type);
s += " order=" + string_from_int (ifr->order);
s += " sample-rate=" + string_from_float (ifr->sampling_frequency);
- s += " passband-edge=" + string_from_float (ifr->passband_edge);
if (ifr->kind == BSE_IIR_FILTER_CHEBYSHEV1 || ifr->kind == BSE_IIR_FILTER_ELLIPTIC)
s += " passband-ripple-db=" + string_from_float (ifr->passband_ripple_db);
+ s += " passband-edge=" + string_from_float (ifr->passband_edge);
if (ifr->type == BSE_IIR_FILTER_BAND_PASS || ifr->type == BSE_IIR_FILTER_BAND_STOP)
s += " passband-edge2=" + string_from_float (ifr->passband_edge2);
+ if (ifr->kind == BSE_IIR_FILTER_ELLIPTIC && ifr->stopband_db < 0)
+ s += " stopband-db=" + string_from_float (ifr->stopband_db);
if (ifr->kind == BSE_IIR_FILTER_ELLIPTIC && ifr->stopband_edge > 0)
s += " stopband-edge=" + string_from_float (ifr->stopband_edge);
- if (ifr->kind == BSE_IIR_FILTER_ELLIPTIC && ifr->stopband_db < 0)
- s += " stopband-db=" + string_from_float (ifr->stopband_db);
return g_strdup (s.c_str());
}
Modified: trunk/bse/bsemath.c
===================================================================
--- trunk/bse/bsemath.c 2006-11-02 21:31:58 UTC (rev 4052)
+++ trunk/bse/bsemath.c 2006-11-02 21:45:13 UTC (rev 4053)
@@ -21,7 +21,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
-#define RING_BUFFER_LENGTH (16)
+#define RING_BUFFER_LENGTH (256) // FIXME: simlpy dup strings in the API
#define PRINTF_DIGITS "1270"
#define FLOAT_STRING_SIZE (2048)
Modified: trunk/bse/tests/filtertest.cc
===================================================================
--- trunk/bse/tests/filtertest.cc 2006-11-02 21:31:58 UTC (rev 4052)
+++ trunk/bse/tests/filtertest.cc 2006-11-02 21:45:13 UTC (rev 4053)
@@ -21,6 +21,8 @@
#include <sfi/sfitests.h>
#include <bse/bsefilter.h>
#include <bse/bsemain.h>
+#include <bse/gslfilter.h> // FIXME
+#include <bse/bseglobals.h> // FIXME
#include "topconfig.h"
#include <math.h>
@@ -28,7 +30,57 @@
using std::max;
using std::min;
+static inline double
+sqr (register double a)
+{
+ return a * a;
+}
+
+static inline uint
+complex_find_nearest (const Complex *zp,
+ uint n_zps,
+ const Complex *zps)
+{
+ const Complex z = *zp;
+ uint j = 0;
+ double last = sqr (real (z) - real (zps[j])) + sqr (imag (z) - imag (zps[j]));
+ if (last == 0.0)
+ return j;
+ for (uint i = 1; i < n_zps; i++)
+ {
+ double dist2 = sqr (real (z) - real (zps[i])) + sqr (imag (z) - imag (zps[i]));
+ if (dist2 < last)
+ {
+ last = dist2;
+ j = i;
+ if (last == 0.0)
+ return j;
+ }
+ }
+ return j;
+}
+
static double
+compare_zeros (uint n_zeros,
+ const Complex *czeros,
+ const double *rizeros)
+{
+ Complex *z2 = (Complex*) alloca (sizeof (Complex) * n_zeros);
+ for (uint i = 0; i < n_zeros; i++)
+ z2[i] = Complex (rizeros[i * 2], rizeros[i * 2 + 1]);
+ double max_eps = 0;
+ for (uint i = 0; i < n_zeros; i++)
+ {
+ uint j = complex_find_nearest (&czeros[i], n_zeros - i, z2);
+ double reps = fabs (real (z2[j]) - real (czeros[i]));
+ double ieps = fabs (imag (z2[j]) - imag (czeros[i]));
+ z2[j] = z2[n_zeros - i - 1]; // optimization of: swap (z2[last], z2[j]);
+ max_eps = max (max_eps, max (reps, ieps));
+ }
+ return max_eps;
+}
+
+static double
compare_coefficients (const BseIIRFilterDesign *fdes,
uint n_dncoeffs,
const double *dncoeffs)
@@ -154,15 +206,15 @@
}
static void
-exit_with_iir_filter_gnuplot (const BseIIRFilterRequest *fireq,
- const BseIIRFilterDesign *fdes,
- const char *fname,
- double passband_ripple_db = NAN,
- double passband_edge = NAN,
- double passband_edge2 = NAN,
- double stopband_db = NAN,
- double stopband_edge = NAN,
- double stopband_edge2 = NAN)
+noexit_dump_iir_filter_gnuplot (const BseIIRFilterRequest *fireq,
+ const BseIIRFilterDesign *fdes,
+ const char *fname,
+ double passband_ripple_db = NAN,
+ double passband_edge = NAN,
+ double passband_edge2 = NAN,
+ double stopband_db = NAN,
+ double stopband_edge = NAN,
+ double stopband_edge2 = NAN)
{
double consts[64];
double arrows[64];
@@ -185,6 +237,20 @@
g_printerr ("Filter: %s\n", bse_iir_filter_request_string (fireq));
g_printerr ("Design: %s\n", bse_iir_filter_design_string (fdes));
g_printerr ("GnuplotDump: wrote %s.gp and %s.dat use: gnuplot %s.gp\n", fname, fname, fname);
+}
+
+static void
+exit_with_iir_filter_gnuplot (const BseIIRFilterRequest *fireq,
+ const BseIIRFilterDesign *fdes,
+ const char *fname,
+ double passband_ripple_db = NAN,
+ double passband_edge = NAN,
+ double passband_edge2 = NAN,
+ double stopband_db = NAN,
+ double stopband_edge = NAN,
+ double stopband_edge2 = NAN)
+{
+ noexit_dump_iir_filter_gnuplot (fireq, fdes, fname, passband_ripple_db, passband_edge, passband_edge2, stopband_db, stopband_edge, stopband_edge2);
exit (0);
}
@@ -270,9 +336,8 @@
double start_freq,
double end_freq)
{
- double res1 = max_band_damping_ztrans (fdes, start_freq, end_freq);
- double res2 = max_band_damping_zp (fdes, start_freq, end_freq);
- return min (res1, res2);
+ // double res1 = max_band_damping_ztrans (fdes, start_freq, end_freq);
+ return max_band_damping_zp (fdes, MIN (start_freq, end_freq), MAX (start_freq, end_freq));
}
static double
@@ -280,12 +345,22 @@
double start_freq,
double end_freq)
{
- double res1 = min_band_damping_ztrans (fdes, start_freq, end_freq);
- double res2 = min_band_damping_zp (fdes, start_freq, end_freq);
- return max (res1, res2);
+ // double res1 = min_band_damping_ztrans (fdes, start_freq, end_freq);
+ return min_band_damping_zp (fdes, MIN (start_freq, end_freq), MAX (start_freq, end_freq));
}
static void
+print_filter_on_abort (void *data)
+{
+ void **adata = (void**) data;
+ const BseIIRFilterRequest *req = (BseIIRFilterRequest*) adata[0];
+ const BseIIRFilterDesign *fdes = (BseIIRFilterDesign*) adata[1];
+ noexit_dump_iir_filter_gnuplot (req, fdes, "tmpfilter",
+ -fabs(req->passband_ripple_db), req->passband_edge, req->passband_edge2,
+ req->stopband_db != 0 ? req->stopband_db : NAN, req->stopband_edge, NAN);
+}
+
+static void
butterwoth_tests ()
{
TSTART ("Butterworth");
@@ -295,6 +370,10 @@
BseIIRFilterDesign fdes;
BseIIRFilterRequest req = { BseIIRFilterKind (0), };
req.kind = BSE_IIR_FILTER_BUTTERWORTH;
+ void *abort_data[2];
+ abort_data[0] = (void*) &req;
+ abort_data[1] = &fdes;
+ TABORT_HANDLER (print_filter_on_abort, abort_data);
TOK();
{
@@ -322,9 +401,9 @@
};
eps = compare_coefficients (&fdes, BIRNET_ARRAY_SIZE (dncoeffs), dncoeffs);
TASSERT (eps <= ceps);
- TASSERT (min_band_damping (&fdes, 0, 2000) < gaineps);
- TASSERT (max_band_damping (&fdes, 0, 2000) > -3.0103);
- TASSERT (min_band_damping (&fdes, 3500, 5000) < -68);
+ TASSERT_CMP (min_band_damping (&fdes, 0, 2000), <, gaineps);
+ TASSERT_CMP (max_band_damping (&fdes, 0, 2000), >, -3.0103);
+ TASSERT_CMP (min_band_damping (&fdes, 3500, 5000), <, -68);
if (0)
exit_with_iir_filter_gnuplot (&req, &fdes, "tmpfilter", -3.0103, 2000, NAN, -68, 3500);
}
@@ -348,9 +427,9 @@
};
eps = compare_coefficients (&fdes, BIRNET_ARRAY_SIZE (dncoeffs), dncoeffs);
TASSERT (eps <= ceps);
- TASSERT (min_band_damping (&fdes, 2000, 5000) < gaineps);
- TASSERT (max_band_damping (&fdes, 2000, 5000) > -3.0103);
- TASSERT (min_band_damping (&fdes, 0, 600) < -80);
+ TASSERT_CMP (min_band_damping (&fdes, 2000, 5000), <, gaineps);
+ TASSERT_CMP (max_band_damping (&fdes, 2000, 5000), >, -3.0103);
+ TASSERT_CMP (min_band_damping (&fdes, 0, 600), <, -80);
if (0)
exit_with_iir_filter_gnuplot (&req, &fdes, "tmpfilter", -3.0103, 2000, NAN, -80, 600);
}
@@ -386,10 +465,10 @@
};
eps = compare_coefficients (&fdes, BIRNET_ARRAY_SIZE (dncoeffs), dncoeffs);
TASSERT (eps <= ceps);
- TASSERT (min_band_damping (&fdes, 1500, 3500) < gaineps);
- TASSERT (max_band_damping (&fdes, 1500, 3500) > -3.0103);
- TASSERT (min_band_damping (&fdes, 0, 1000) < -49.5);
- TASSERT (min_band_damping (&fdes, 4000, 5000) < -49.5);
+ TASSERT_CMP (min_band_damping (&fdes, 1500, 3500), <, gaineps);
+ TASSERT_CMP (max_band_damping (&fdes, 1500, 3500), >, -3.0103);
+ TASSERT_CMP (min_band_damping (&fdes, 0, 1000), <, -49.5);
+ TASSERT_CMP (min_band_damping (&fdes, 4000, 5000), <, -49.5);
if (0)
exit_with_iir_filter_gnuplot (&req, &fdes, "tmpfilter", -3.0103, 1500, 3500, -49.5, 1000, 4000);
}
@@ -435,10 +514,10 @@
};
eps = compare_coefficients (&fdes, BIRNET_ARRAY_SIZE (dncoeffs), dncoeffs);
TASSERT (eps <= ceps);
- TASSERT (min_band_damping (&fdes, 0, 1000) < gaineps);
- TASSERT (max_band_damping (&fdes, 0, 1000) > -3.0103);
- TASSERT (min_band_damping (&fdes, 1500, 3500) < -77);
- TASSERT (max_band_damping (&fdes, 4000, 5000) > -3.0103);
+ TASSERT_CMP (min_band_damping (&fdes, 0, 1000), <, gaineps);
+ TASSERT_CMP (max_band_damping (&fdes, 0, 1000), >, -3.0103);
+ TASSERT_CMP (min_band_damping (&fdes, 1500, 3500), <, -77);
+ TASSERT_CMP (max_band_damping (&fdes, 4000, 5000), >, -3.0103);
if (0)
exit_with_iir_filter_gnuplot (&req, &fdes, "tmpfilter", -3.0103, 1000, 4000, -77, 1500, 3500);
}
@@ -450,20 +529,24 @@
static void
chebychev1_tests ()
{
- TSTART ("Chebyshev1");
bool success;
double eps;
- const double ceps = 8e-13, gaineps = 1e-7;
+ TSTART ("Chebyshev1");
BseIIRFilterDesign fdes;
BseIIRFilterRequest req = { BseIIRFilterKind (0), };
req.kind = BSE_IIR_FILTER_CHEBYSHEV1;
+ void *abort_data[2];
+ abort_data[0] = (void*) &req;
+ abort_data[1] = &fdes;
+ TABORT_HANDLER (print_filter_on_abort, abort_data);
+ const double ceps = 8e-13, gaineps = 1e-7;
TOK();
{
req.type = BSE_IIR_FILTER_LOW_PASS;
req.order = 8;
req.sampling_frequency = 20000;
- req.passband_ripple_db = 1.55;
+ req.passband_ripple_db = 1.5500;
req.passband_edge = 3000;
success = bse_iir_filter_design (&req, &fdes);
TASSERT (success == true);
@@ -480,9 +563,9 @@
};
eps = compare_coefficients (&fdes, BIRNET_ARRAY_SIZE (dncoeffs), dncoeffs);
TASSERT (eps <= ceps);
- TASSERT (min_band_damping (&fdes, 0, 3000) < gaineps);
- TASSERT (max_band_damping (&fdes, 0, 3000) > -1.55);
- TASSERT (min_band_damping (&fdes, 5000, 10000) < -80);
+ TASSERT_CMP (min_band_damping (&fdes, 0, 3000), <, gaineps);
+ TASSERT_CMP (max_band_damping (&fdes, 0, 3000), >, -1.5501);
+ TASSERT_CMP (min_band_damping (&fdes, 5000, 10000), <, -80);
if (0)
exit_with_iir_filter_gnuplot (&req, &fdes, "tmpfilter", -1.55, 3000, NAN, -80, 5000);
}
@@ -507,9 +590,9 @@
};
eps = compare_coefficients (&fdes, BIRNET_ARRAY_SIZE (dncoeffs), dncoeffs);
TASSERT (eps <= ceps);
- TASSERT (min_band_damping (&fdes, 600, 5000) < gaineps);
- TASSERT (max_band_damping (&fdes, 600, 5000) >= -0.101);
- TASSERT (min_band_damping (&fdes, 0, 250) < -70);
+ TASSERT_CMP (min_band_damping (&fdes, 600, 5000), <, gaineps);
+ TASSERT_CMP (max_band_damping (&fdes, 600, 5000), >, -0.101);
+ TASSERT_CMP (min_band_damping (&fdes, 0, 250), <, -70);
if (0)
exit_with_iir_filter_gnuplot (&req, &fdes, "tmpfilter", -0.1, 600, NAN, -70, 250);
}
@@ -548,10 +631,10 @@
};
eps = compare_coefficients (&fdes, BIRNET_ARRAY_SIZE (dncoeffs), dncoeffs);
TASSERT (eps <= ceps);
- TASSERT (min_band_damping (&fdes, 3500, 9500) < gaineps);
- TASSERT (max_band_damping (&fdes, 3500, 9500) > -1.801);
- TASSERT (min_band_damping (&fdes, 0, 3000) < -55);
- TASSERT (min_band_damping (&fdes, 10200, 15000) < -55);
+ TASSERT_CMP (min_band_damping (&fdes, 3500, 9500), <, gaineps);
+ TASSERT_CMP (max_band_damping (&fdes, 3500, 9500), >, -1.801);
+ TASSERT_CMP (min_band_damping (&fdes, 0, 3000), <, -55);
+ TASSERT_CMP (min_band_damping (&fdes, 10200, 15000), <, -55);
if (0)
exit_with_iir_filter_gnuplot (&req, &fdes, "tmpfilter", -1.801, 3500, 9500, -55, 3000, 10200);
}
@@ -596,10 +679,10 @@
};
eps = compare_coefficients (&fdes, BIRNET_ARRAY_SIZE (dncoeffs), dncoeffs);
TASSERT (eps <= ceps);
- TASSERT (min_band_damping (&fdes, 0, 8000) < gaineps);
- TASSERT (max_band_damping (&fdes, 0, 8000) > -1.001);
- TASSERT (min_band_damping (&fdes, 8500, 11500) < -78);
- TASSERT (max_band_damping (&fdes, 12000, 20000) > -1.001);
+ TASSERT_CMP (min_band_damping (&fdes, 0, 8000), <, gaineps);
+ TASSERT_CMP (max_band_damping (&fdes, 0, 8000), >, -1.001);
+ TASSERT_CMP (min_band_damping (&fdes, 8500, 11500), <, -78);
+ TASSERT_CMP (max_band_damping (&fdes, 12000, 20000), >, -1.001);
if (0)
exit_with_iir_filter_gnuplot (&req, &fdes, "tmpfilter", -1.001, 8000, 12000, -78, 8500, 11500);
}
@@ -615,32 +698,131 @@
const BseIIRFilterRequest *filter_request;
const double *filter_coefficients;
uint n_filter_coefficients;
- } filters[1000000];
+ double gain;
+ uint n_zeros;
+ const double *zeros;
+ uint n_poles;
+ const double *poles;
+ } filters[100000] = { { 0, } };
uint index = 0;
- // #include "../../r+d-files/tmp.c"
+
+ { // ellf gain is too high
+ static const BseIIRFilterRequest filter_request = {
+ /* kind = */ BSE_IIR_FILTER_ELLIPTIC,
+ /* type = */ BSE_IIR_FILTER_HIGH_PASS,
+ /* order = */ 20,
+ /* sampling_frequency = */ 1073741824.0000,
+ /* passband_ripple_db = */ 1.3719436899999999,
+ /* passband_edge = */ 483183820.79999995,
+ /* passband_edge2 = */ 0,
+ /* stopband_edge = */ 0,
+ /* stopband_db = */ -26,
+ };
+ filters[index].filter_request = &filter_request;
+ filters[index].gain = +6.50971316315766546e-02;
+ index++;
+ }
+ { // ellf gain is too high
+ static const BseIIRFilterRequest filter_request = {
+ /* kind = */ BSE_IIR_FILTER_ELLIPTIC,
+ /* type = */ BSE_IIR_FILTER_BAND_PASS,
+ /* order = */ 19,
+ /* sampling_frequency = */ 3333.0000,
+ /* passband_ripple_db = */ 0.01,
+ /* passband_edge = */ 1333.2,
+ /* passband_edge2 = */ 999.89999999999998,
+ /* stopband_edge = */ 0,
+ /* stopband_db = */ -120,
+ };
+ filters[index].filter_request = &filter_request;
+ filters[index].gain = +1.21552945102360275e-05;
+ index++;
+ }
+ { // ellf gain is too high
+ static const BseIIRFilterRequest filter_request = {
+ /* kind = */ BSE_IIR_FILTER_ELLIPTIC,
+ /* type = */ BSE_IIR_FILTER_BAND_PASS,
+ /* order = */ 20,
+ /* sampling_frequency = */ 8000.0000,
+ /* passband_ripple_db = */ 0.01,
+ /* passband_edge = */ 3200,
+ /* passband_edge2 = */ 2400,
+ /* stopband_edge = */ 0,
+ /* stopband_db = */ -26,
+ };
+ filters[index].filter_request = &filter_request;
+ filters[index].gain = +1.12649838606861938e-01;
+ index++;
+ }
+
+ if (0) { // FIXME: bse gain = 4.3037825362077964
+ static const BseIIRFilterRequest filter_request = {
+ /* kind = */ BSE_IIR_FILTER_ELLIPTIC,
+ /* type = */ BSE_IIR_FILTER_BAND_PASS,
+ /* order = */ 36,
+ /* sampling_frequency = */ 3333.0000,
+ /* passband_ripple_db = */ 1.3719436899999999,
+ /* passband_edge = */ 943.23900000000003,
+ /* passband_edge2 = */ 499.94999999999999,
+ /* stopband_edge = */ 0,
+ /* stopband_db = */ -26,
+ };
+ filters[index].filter_request = &filter_request;
+ filters[index].gain = -3.83263619423376167e-01;
+ index++;
+ }
+
+#include "../../r+d-files/tmp.c"
+
uint i;
- const double coefficients_epsilon = 1e-9;
+ const double coefficients_epsilon = 1e-7;
+ const double max_gain = 0.01; // maximum gain in passband
TSTART ("Bruteforce filter checks");
+ void *abort_data[2];
+ TABORT_HANDLER (print_filter_on_abort, abort_data);
+ const uint n_filters_tok = 13;
for (i = 0; i < index; i++)
{
const BseIIRFilterRequest *req = filters[i].filter_request;
- const uint n_coefficients = filters[i].n_filter_coefficients;
- const double *coefficients = filters[i].filter_coefficients;
BseIIRFilterDesign fdes;
+ abort_data[0] = (void*) req;
+ abort_data[1] = &fdes;
bool success = bse_iir_filter_design (req, &fdes);
- TASSERT (success == true);
- double eps = compare_coefficients (&fdes, n_coefficients, coefficients);
- if (eps > coefficients_epsilon)
+ TCHECK (success == true);
+ if (filters[i].zeros)
+ TCHECK_CMP (filters[i].n_zeros, ==, fdes.n_zeros);
+ if (filters[i].poles)
+ TCHECK_CMP (filters[i].n_poles, ==, fdes.n_poles);
+ double zeps = filters[i].zeros ? compare_zeros (fdes.n_zeros, fdes.zz, filters[i].zeros) : 0;
+ double peps = filters[i].poles ? compare_zeros (fdes.n_poles, fdes.zp, filters[i].poles) : 0;
+ TCHECK_CMP (zeps, <, coefficients_epsilon);
+ TCHECK_CMP (peps, <, coefficients_epsilon);
+ /* broad gain check */
+ TCHECK_CMP (min_band_damping (&fdes, 0, 0.5 * req->sampling_frequency), <, max_gain);
+ /* finer gain checks */
+ double passband_ripple_db = req->kind == BSE_IIR_FILTER_BUTTERWORTH ? -3.010299956639811952 : -req->passband_ripple_db;
+ passband_ripple_db -= 0.01; // add a bit of fudge for evaluation artefacts
+ if (req->type == BSE_IIR_FILTER_LOW_PASS || req->type == BSE_IIR_FILTER_BAND_STOP)
{
- g_printerr ("EPSILON FAILED: %.16g %.16g\n", eps, coefficients_epsilon);
- g_printerr ("EPSILON FAILED: %.16g %.16g\n", eps, coefficients_epsilon);
- g_printerr ("EPSILON FAILED: %.16g %.16g\n", eps, coefficients_epsilon);
- exit_with_iir_filter_gnuplot (req, &fdes, "tmpfilter",
- req->passband_ripple_db, req->passband_edge, req->passband_edge2,
- req->stopband_db != 0 ? req->stopband_db : NAN, req->stopband_edge, NAN);
- TASSERT (eps <= coefficients_epsilon);
+ TCHECK_CMP (min_band_damping (&fdes, 0, req->passband_edge), <, max_gain);
+ TCHECK_CMP (max_band_damping (&fdes, 0, req->passband_edge), >, passband_ripple_db);
}
- else
+ if (req->type == BSE_IIR_FILTER_HIGH_PASS)
+ {
+ TCHECK_CMP (min_band_damping (&fdes, req->passband_edge, 0.5 * req->sampling_frequency), <, max_gain);
+ TCHECK_CMP (max_band_damping (&fdes, req->passband_edge, 0.5 * req->sampling_frequency), >, passband_ripple_db);
+ }
+ if (req->type == BSE_IIR_FILTER_BAND_PASS)
+ {
+ TCHECK_CMP (min_band_damping (&fdes, req->passband_edge, req->passband_edge2), <, max_gain);
+ TCHECK_CMP (max_band_damping (&fdes, req->passband_edge, req->passband_edge2), >, passband_ripple_db);
+ }
+ if (req->type == BSE_IIR_FILTER_BAND_STOP)
+ {
+ TCHECK_CMP (min_band_damping (&fdes, req->passband_edge2, 0.5 * req->sampling_frequency), <, max_gain);
+ TCHECK_CMP (max_band_damping (&fdes, req->passband_edge2, 0.5 * req->sampling_frequency), >, passband_ripple_db);
+ }
+ if (i % n_filters_tok == 0)
TOK();
}
TDONE();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]