r3992 - in trunk: . tests/bse
- From: stw svn gnome org
- To: svn-commits-list gnome org
- Subject: r3992 - in trunk: . tests/bse
- Date: Fri, 20 Oct 2006 17:09:56 -0400 (EDT)
Author: stw
Date: 2006-10-20 17:09:48 -0400 (Fri, 20 Oct 2006)
New Revision: 3992
Modified:
trunk/ChangeLog
trunk/tests/bse/filtertest.cc
Log:
Fri Oct 20 23:03:36 2006 Stefan Westerfeld <stefan space twc de>
* tests/bse/filtertest.cc: More refactoring.
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2006-10-20 21:05:20 UTC (rev 3991)
+++ trunk/ChangeLog 2006-10-20 21:09:48 UTC (rev 3992)
@@ -1,3 +1,7 @@
+Fri Oct 20 23:03:36 2006 Stefan Westerfeld <stefan space twc de>
+
+ * tests/bse/filtertest.cc: More refactoring.
+
Fri Oct 20 14:01:19 2006 Stefan Westerfeld <stefan space twc de>
* tests/bse/filtertest.cc: Refactoring. Adapted to the changes of the
Modified: trunk/tests/bse/filtertest.cc
===================================================================
--- trunk/tests/bse/filtertest.cc 2006-10-20 21:05:20 UTC (rev 3991)
+++ trunk/tests/bse/filtertest.cc 2006-10-20 21:09:48 UTC (rev 3992)
@@ -164,28 +164,43 @@
public:
enum TestMode
{
- TEST_NOTHING = 0,
TEST_COMPUTED_RESPONSE = 1,
- TEST_SCANNED_RESPONSE = 2,
- TEST_DUMP_GNUPLOT_DATA = 4,
- TEST_COMPUTED_AND_SCANNED_RESPONSE = TEST_COMPUTED_RESPONSE | TEST_SCANNED_RESPONSE
+ TEST_SCANNED_RESPONSE = 2
};
private:
+ struct Band {
+ double freq_start;
+ double freq_end;
+ double min_resp_db;
+ double max_resp_db;
+
+ Band (double freq_start,
+ double freq_end,
+ double min_resp_db,
+ double max_resp_db) :
+ freq_start (freq_start),
+ freq_end (freq_end),
+ min_resp_db (min_resp_db),
+ max_resp_db (max_resp_db)
+ {
+ }
+ };
+
string m_name;
guint m_order;
- TestMode m_test_mode;
+ string m_gp_short_name;
vector<double> m_a, m_b;
set<double> m_gp_arrows;
set<double> m_gp_lines;
+ vector<Band> m_spec_bands;
static const double FS = 10000.0;
- const double delta_f;
static const double MIN_DB = -1000;
static const double DB_EPSILON = 0.01; /* for comparisions */
double
- response (double f)
+ response (double f) const
{
double u = 2.0 * PI * f / FS;
std::complex<double> z (cos (u), sin (u)); /* exp( j omega T ) */
@@ -202,128 +217,125 @@
}
double
- scan_response (double f)
+ scan_response (double f) const
{
const double MAX_SCAN_FREQ = FS / 2 - 0.01;
f = min (f, MAX_SCAN_FREQ);
return gsl_filter_sine_scan (m_order, &m_a[0], &m_b[0], f, FS);
}
-public:
- FilterTest (const char *name,
- guint order,
- const double *coefficients,
- TestMode test_mode,
- double scan_points) :
- m_name (name),
- m_order (order),
- m_test_mode (test_mode),
- delta_f ((FS / 2) / scan_points)
- {
- TSTART("%s, Order %d", name, order);
-
- for (guint i = 0; i < m_order * 2 + 2; i += 2)
- {
- m_b.push_back (coefficients[i]);
- m_a.push_back (coefficients[i+1]);
- }
- }
- ~FilterTest()
- {
- TDONE();
- }
void
- check_response_db (double freq,
- double min_resp_db,
- double max_resp_db)
+ check_response_db (double freq,
+ double min_resp_db,
+ double max_resp_db,
+ TestMode test_mode) const
{
- if (m_test_mode & TEST_COMPUTED_RESPONSE)
+ double resp;
+ switch (test_mode)
{
- double resp = bse_db_from_factor (response (freq), MIN_DB);
- if (!(resp > min_resp_db - DB_EPSILON) || !(resp < max_resp_db + DB_EPSILON))
- {
- g_printerr ("\n*** check_response_db: computed response at frequency %f is %f\n", freq, resp);
- g_printerr ("*** check_response_db: but should be in interval [%f..%f]\n", min_resp_db, max_resp_db);
- }
- TCHECK (resp > min_resp_db - DB_EPSILON);
- TCHECK (resp < max_resp_db + DB_EPSILON);
+ case TEST_COMPUTED_RESPONSE: resp = bse_db_from_factor (response (freq), MIN_DB);
+ break;
+ case TEST_SCANNED_RESPONSE: resp = bse_db_from_factor (scan_response (freq), MIN_DB);
+ break;
+ default: return; /* huh? */
}
-
- if (m_test_mode & TEST_SCANNED_RESPONSE)
+ if (!(resp > min_resp_db - DB_EPSILON) || !(resp < max_resp_db + DB_EPSILON))
{
- double scan_resp = bse_db_from_factor (scan_response (freq), MIN_DB);
- if (!(scan_resp > min_resp_db - DB_EPSILON) || !(scan_resp < max_resp_db + DB_EPSILON))
- {
- g_printerr ("\n*** check_response_db: scanned response at frequency %f is %f\n", freq, scan_resp);
- g_printerr ("*** check_response_db: but should be in interval [%f..%f]\n", min_resp_db, max_resp_db);
- }
- TCHECK (scan_resp > min_resp_db - DB_EPSILON);
- TCHECK (scan_resp < max_resp_db + DB_EPSILON);
+ g_printerr ("\n*** check_response_db: computed response at frequency %f is %f\n", freq, resp);
+ g_printerr ("*** check_response_db: but should be in interval [%f..%f]\n", min_resp_db, max_resp_db);
}
+ TCHECK (resp > min_resp_db - DB_EPSILON);
+ TCHECK (resp < max_resp_db + DB_EPSILON);
}
void
- check_band (double freq_start,
- double freq_end,
- double min_resp_db,
- double max_resp_db)
+ check_band (const Band& band,
+ TestMode test_mode,
+ guint scan_points) const
{
- g_return_if_fail (freq_start <= freq_end);
- g_return_if_fail (freq_end <= FS/2);
+ const double delta_f = (FS / 2) / scan_points;
- /* we don't need to actually perform the checks just to dump the gnuplot data */
- if (options.dump_gnuplot_data)
- return;
+ g_return_if_fail (band.freq_start <= band.freq_end);
+ g_return_if_fail (band.freq_end <= FS/2);
TPRINT ("checking band: response in interval [%f..%f] should be in interval [%f..%f] dB\n",
- freq_start, freq_end, min_resp_db, max_resp_db);
+ band.freq_start, band.freq_end, band.min_resp_db, band.max_resp_db);
int tok = 0;
int tok_dots = int ((FS / delta_f) / 50) + 1;
- for (double f = freq_start; f < freq_end; f += delta_f)
+ for (double f = band.freq_start; f < band.freq_end; f += delta_f)
{
if (tok++ % tok_dots == 0)
TOK();
- check_response_db (f, min_resp_db, max_resp_db);
+ check_response_db (f, band.min_resp_db, band.max_resp_db, test_mode);
}
- if (freq_start != freq_end)
- check_response_db (freq_end, min_resp_db, max_resp_db);
+ if (band.freq_start != band.freq_end)
+ check_response_db (band.freq_end, band.min_resp_db, band.max_resp_db, test_mode);
}
+public:
+ FilterTest (const char *name,
+ guint order,
+ const double *coefficients,
+ const char *gp_short_name) :
+ m_name (name),
+ m_order (order),
+ m_gp_short_name (gp_short_name)
+ {
+
+ for (guint i = 0; i < m_order * 2 + 2; i += 2)
+ {
+ m_b.push_back (coefficients[i]);
+ m_a.push_back (coefficients[i+1]);
+ }
+ }
+
+ /* construction phase: used to add a passband to the specification */
void
- check_passband (double freq_start,
+ add_passband (double freq_start,
double freq_end,
double ripple_db)
{
m_gp_arrows.insert (freq_start);
m_gp_arrows.insert (freq_end);
m_gp_lines.insert (ripple_db);
+ m_spec_bands.push_back (Band (freq_start, freq_end, ripple_db, 0));
+ }
- check_band (freq_start, freq_end, ripple_db, 0);
- }
+ /* construction phase: used to add a stopband to the specification */
void
- check_stopband (double freq_start,
- double freq_end,
- double ripple_db)
+ add_stopband (double freq_start,
+ double freq_end,
+ double ripple_db)
{
m_gp_arrows.insert (freq_start);
m_gp_arrows.insert (freq_end);
m_gp_lines.insert (ripple_db);
+ m_spec_bands.push_back (Band (freq_start, freq_end, MIN_DB, ripple_db));
+ }
- check_band (freq_start, freq_end, MIN_DB, ripple_db);
+ /* actually check filter against specification */
+ void
+ perform_checks (TestMode test_mode,
+ guint scan_points) const
+ {
+ TSTART("%s, Order %d", m_name.c_str(), m_order);
+ for (vector<Band>::const_iterator sbi = m_spec_bands.begin(); sbi != m_spec_bands.end(); sbi++)
+ check_band (*sbi, test_mode, scan_points);
+ TDONE();
}
/**
- * creates two files, a datafile named filename_prefix ".data" and a gnuplot
- * script called filename_prefix ".gp", which can be used to plot the filter,
- * including the specification checks
+ * creates two files, a datafile named filename_prefix m_gp_short_name
+ * ".data" and a gnuplot script called filename_prefix m_gp_short_name ".gp",
+ * which can be used to plot the filter, including the specification checks
*/
bool
- dump_gp (const string& filename_prefix)
+ dump_gnuplot_data (const string& filename_prefix,
+ guint scan_points = 1000)
{
- if ((m_test_mode & TEST_DUMP_GNUPLOT_DATA) == 0)
- return false;
+ const double delta_f = (FS / 2) / scan_points;
- string data_filename = filename_prefix + ".data";
- string gp_filename = filename_prefix + ".gp";
+ string data_filename = filename_prefix + m_gp_short_name + ".data";
+ string gp_filename = filename_prefix + m_gp_short_name + ".gp";
FILE *data_file = fopen (data_filename.c_str(), "w");
if (!data_file)
@@ -332,7 +344,7 @@
data_filename.c_str(), strerror (errno));
return false;
}
- FILE *gp_file = fopen ((filename_prefix + ".gp").c_str(), "w");
+ FILE *gp_file = fopen (gp_filename.c_str(), "w");
if (!gp_file)
{
g_printerr ("\ncan't open gnuplot scriptfile '%s': %s\n",
@@ -340,7 +352,7 @@
fclose (data_file);
return false;
}
- g_printerr ("creating gnuplot files '%s.gp', '%s.data'", filename_prefix.c_str(), filename_prefix.c_str());
+ g_printerr ("creating gnuplot files '%s', '%s'... ", gp_filename.c_str(), data_filename.c_str());
for (double f = 0; f < FS/2; f += delta_f)
{
@@ -359,8 +371,8 @@
for (set<double>::iterator ai = m_gp_arrows.begin(); ai != m_gp_arrows.end(); ai++)
fprintf (gp_file, " %f", *ai);
fprintf (gp_file, "\n");
- fprintf (gp_file, "plot 0, '%s.data' using ($1):($3), '%s.data' using ($1):($2) with lines",
- filename_prefix.c_str(), filename_prefix.c_str());
+ fprintf (gp_file, "plot 0, '%s' using ($1):($3), '%s' using ($1):($2) with lines",
+ data_filename.c_str(), data_filename.c_str());
for (set<double>::iterator li = m_gp_lines.begin(); li != m_gp_lines.end(); li++)
fprintf (gp_file, ", %f", *li);
fprintf (gp_file, "\n");
@@ -368,13 +380,14 @@
fclose (gp_file);
fclose (data_file);
+
+ g_printerr ("ok.\n");
return 0;
}
};
void
-check_filters (FilterTest::TestMode test_mode,
- double scan_points)
+setup_all_filter_tests (vector<FilterTest>& filter_tests)
{
{
//! ORDER=8 MIX_FREQ=10000 PASS1=2000 yet.sh blp
@@ -390,10 +403,10 @@
+8.61368381197359644919E-04, +2.27184001245132058747E-03, // BSEcxxmgc
}; // BSEcxxmgc
- FilterTest bw8 ("Butterworth Lowpass 2000 Hz", 8, coeffs, test_mode, scan_points);
- bw8.check_passband (0, 2000, bse_db_from_factor (1/sqrt(2), -30));
- bw8.check_stopband (3500, 5000, -68);
- bw8.dump_gp ("filtertest_bw8");
+ FilterTest bw8 ("Butterworth Lowpass 2000 Hz", 8, coeffs, "bw8");
+ bw8.add_passband (0, 2000, bse_db_from_factor (1/sqrt(2), -30));
+ bw8.add_stopband (3500, 5000, -68);
+ filter_tests.push_back (bw8);
}
{
//! ORDER=12 MIX_FREQ=10000 PASS1=2000 PASS_RIPPLE=0.5 STOP_DB=-96 yet.sh elpd
@@ -413,12 +426,12 @@
+2.41243520047625281677E-01, +1.05368736204784763100E-03, // BSEcxxmgc
}; // BSEcxxmgc
- FilterTest ell12 ("Elliptic Lowpass 2000 Hz", 12, coeffs, test_mode, scan_points);
- ell12.check_passband (0, 2000, -0.5);
+ FilterTest ell12 ("Elliptic Lowpass 2000 Hz", 12, coeffs, "ell12");
+ ell12.add_passband (0, 2000, -0.5);
/* FIXME: we should get better results (= -96 dB) if we implement this filter with cascading lowpasses */
- ell12.check_stopband (2160, 5000, -96);
- ell12.dump_gp ("filtertest_ell12");
+ ell12.add_stopband (2160, 5000, -96);
+ filter_tests.push_back (ell12);
}
{
//! ORDER=7 MIX_FREQ=10000 PASS1=600 PASS_RIPPLE=0.1 yet.sh chp
@@ -433,10 +446,10 @@
-1.17830171950224868449E-01, -3.56249822046611874793E-01, // BSEcxxmgc
}; // BSEcxxmgc
- FilterTest chp7 ("Chebychev Highpass 600 Hz", 7, coeffs, test_mode, scan_points);
- chp7.check_passband (600, 5000, -0.1);
- chp7.check_stopband (0, 250, -70);
- chp7.dump_gp ("filtertest_chp7");
+ FilterTest chp7 ("Chebychev Highpass 600 Hz", 7, coeffs, "chp7");
+ chp7.add_passband (600, 5000, -0.1);
+ chp7.add_stopband (0, 250, -70);
+ filter_tests.push_back (chp7);
}
{
//! ORDER=9 MIX_FREQ=10000 PASS1=1500 PASS2=3500 yet.sh bbp
@@ -462,11 +475,11 @@
+3.55580604257624494427E-04, -1.06539452359780476010E-03, // BSEcxxmgc
}; // BSEcxxmgc
- FilterTest bbp18 ("Butterworth Bandpass 1500-3500 Hz", 18, coeffs, test_mode, scan_points);
- bbp18.check_passband (1500, 3500, bse_db_from_factor (1/sqrt(2), -30));
- bbp18.check_stopband (0, 1000, -49.5);
- bbp18.check_stopband (4000, 5000, -49.5);
- bbp18.dump_gp ("filtertest_bbp18");
+ FilterTest bbp18 ("Butterworth Bandpass 1500-3500 Hz", 18, coeffs, "bbp18");
+ bbp18.add_passband (1500, 3500, bse_db_from_factor (1/sqrt(2), -30));
+ bbp18.add_stopband (0, 1000, -49.5);
+ bbp18.add_stopband (4000, 5000, -49.5);
+ filter_tests.push_back (bbp18);
}
{
//! ORDER=2 MIX_FREQ=10000 PASS1=300 PASS2=1000 PASS_RIPPLE=2.5 STOP1_EDGE=400 yet.sh ebsh
@@ -477,30 +490,35 @@
-2.73689660911365040263E+00, -2.26195685035092974857E+00, // BSEcxxmgc
+7.02817346525631658771E-01, +6.05473613799674903468E-01, // BSEcxxmgc
}; // BSEcxxmgc
- FilterTest ebsh4 ("Elliptic Bandstop 300-1000 Hz", 4, coeffs, test_mode, scan_points);
- ebsh4.check_passband (0, 300, -2.5);
- ebsh4.check_stopband (400, 755, -21.5);
- ebsh4.check_passband (1000, 5000, -2.5);
- ebsh4.dump_gp ("filtertest_ebsh4");
+ FilterTest ebsh4 ("Elliptic Bandstop 300-1000 Hz", 4, coeffs, "ebsh4");
+ ebsh4.add_passband (0, 300, -2.5);
+ ebsh4.add_stopband (400, 755, -21.5);
+ ebsh4.add_passband (1000, 5000, -2.5);
+ filter_tests.push_back (ebsh4);
}
}
void
-check_computed_response()
+check_computed_response (const vector<FilterTest>& filter_tests)
{
- check_filters (FilterTest::TEST_COMPUTED_RESPONSE, 10000);
+ g_printerr ("---> checking computed filter responses:\n");
+ for (vector<FilterTest>::const_iterator fi = filter_tests.begin(); fi != filter_tests.end(); fi++)
+ fi->perform_checks (FilterTest::TEST_COMPUTED_RESPONSE, 10000);
}
void
-check_scanned_response()
+check_scanned_response (const vector<FilterTest>& filter_tests)
{
- check_filters (FilterTest::TEST_SCANNED_RESPONSE, 67); /* prime number scan points */
+ g_printerr ("---> checking scanned filter responses:\n");
+ for (vector<FilterTest>::const_iterator fi = filter_tests.begin(); fi != filter_tests.end(); fi++)
+ fi->perform_checks (FilterTest::TEST_SCANNED_RESPONSE, 67); /* prime number scan points */
}
void
-dump_gnuplot_data()
+dump_gnuplot_data (vector<FilterTest>& filter_tests)
{
- check_filters (FilterTest::TEST_DUMP_GNUPLOT_DATA, 1000);
+ for (vector<FilterTest>::iterator fi = filter_tests.begin(); fi != filter_tests.end(); fi++)
+ fi->dump_gnuplot_data ("filtertest_");
}
int
@@ -510,13 +528,25 @@
bse_init_test (&argc, &argv, NULL);
options.parse (&argc, &argv);
+ if (argc > 1)
+ {
+ int a;
+ for (a = 1; a < argc; a++)
+ g_printerr ("%s: unknown extra arg: %s\n", options.program_name.c_str(), argv[a]);
+ g_printerr ("%s: use the --help option for help.\n", options.program_name.c_str());
+ return 1;
+ }
+
+ vector<FilterTest> filter_tests;
+ setup_all_filter_tests (filter_tests);
+
if (options.dump_gnuplot_data)
{
- dump_gnuplot_data();
+ dump_gnuplot_data (filter_tests);
}
else
{
- check_computed_response();
- check_scanned_response();
+ check_computed_response (filter_tests);
+ check_scanned_response (filter_tests);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]