/* GSL - Generic Sound Layer * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #define PREC "15" static void usage (void) G_GNUC_NORETURN; static guint shift_argc = 0; static const gchar **shift_argv = NULL; static const gchar* shift (void) { const gchar *arg; if (shift_argc > 1) { shift_argc--; arg = shift_argv++[1]; if (!arg) arg = ""; } else arg = NULL; return arg; } static const gchar* pshift (void) { const gchar *arg = shift (); return arg ? arg : ""; } int main (int argc, char *argv[]) { const gchar *arg; /* iir filter parameters */ enum { FILTER_GNUPLOT, FILTER_SCAN } filter_mode = FILTER_GNUPLOT; const gchar *filter_label = 0; gdouble *a, *b; guint order = 0; shift_argc = argc; shift_argv = (gchar **)argv; if (!g_thread_supported ()) g_thread_init (NULL); gsl_init (NULL, NULL); arg = shift (); if (!arg) usage (); restart: a = b = 0; if (strcmp (arg, "wave-scan") == 0) { const gchar *file = pshift (); while (file) { GslWaveFileInfo *fi; GslErrorType error; fi = gsl_wave_file_info_load (file, &error); if (fi) { guint i; g_print ("Loader \"%s\" found %u waves in \"%s\":\n", fi->loader->name, fi->n_waves, file); for (i = 0; i < fi->n_waves; i++) g_print ("%u) %s\n", i + 1, fi->waves[i].name); gsl_wave_file_info_unref (fi); } else g_print ("Failed to scan \"%s\": %s\n", file, gsl_strerror (error)); file = pshift (); if (!file[0]) break; } } else if (strcmp (arg, "file-test") == 0) { const gchar *file = pshift (); g_print ("file test for \"%s\":\n", file); g_print (" is readable : %s\n", gsl_strerror (gsl_check_file (file, "r"))); g_print (" is writable : %s\n", gsl_strerror (gsl_check_file (file, "w"))); g_print (" is executable : %s\n", gsl_strerror (gsl_check_file (file, "x"))); g_print (" is file : %s\n", gsl_strerror (gsl_check_file (file, "f"))); g_print (" is directory : %s\n", gsl_strerror (gsl_check_file (file, "d"))); g_print (" is link : %s\n", gsl_strerror (gsl_check_file (file, "l"))); } else if (strcmp (arg, "rf") == 0) { double x, y, z; x = atof (pshift ()); y = atof (pshift ()); z = atof (pshift ()); g_print ("rf(%f, %f, %f) = %."PREC"f\n", x, y, z, gsl_ellip_rf (x, y, z)); } else if (strcmp (arg, "F") == 0) { double phi, ak; phi = atof (pshift ()); ak = atof (pshift ()); g_print ("F(%f, %f) = %."PREC"f\n", phi, ak, gsl_ellip_F (phi, ak)); } else if (strcmp (arg, "sn") == 0) { double u, emmc; u = atof (pshift ()); emmc = atof (pshift ()); g_print ("sn(%f, %f) = %."PREC"f\n", u, emmc, gsl_ellip_sn (u, emmc)); } else if (strcmp (arg, "snc") == 0) { GslComplex u, emmc; u.re = atof (pshift ()); u.im = atof (pshift ()); emmc.re = atof (pshift ()); emmc.im = atof (pshift ()); g_print ("snc(%s, %s) = %s\n", gsl_complex_str (u), gsl_complex_str (emmc), gsl_complex_str (gsl_complex_ellip_sn (u, emmc))); } else if (strcmp (arg, "sci_snc") == 0) { GslComplex u, k2; u.re = atof (pshift ()); u.im = atof (pshift ()); k2.re = atof (pshift ()); k2.im = atof (pshift ()); g_print ("sci_snc(%s, %s) = %s\n", gsl_complex_str (u), gsl_complex_str (k2), gsl_complex_str (gsl_complex_ellip_sn (u, gsl_complex_sub (gsl_complex (1.0, 0), k2)))); } else if (strcmp (arg, "asn") == 0) { double y, emmc; y = atof (pshift ()); emmc = atof (pshift ()); g_print ("asn(%f, %f) = %."PREC"f\n", y, emmc, gsl_ellip_asn (y, emmc)); } else if (strcmp (arg, "asnc") == 0) { GslComplex y, emmc; y.re = atof (pshift ()); y.im = atof (pshift ()); emmc.re = atof (pshift ()); emmc.im = atof (pshift ()); g_print ("asnc(%s, %s) = %s\n", gsl_complex_str (y), gsl_complex_str (emmc), gsl_complex_str (gsl_complex_ellip_asn (y, emmc))); g_print ("asn(%f, %f = %."PREC"f\n", y.re, emmc.re, gsl_ellip_asn (y.re, emmc.re)); } else if (strcmp (arg, "sci_sn") == 0) { double u, k2; u = atof (pshift ()); k2 = atof (pshift ()); g_print ("sci_sn(%f, %f) = %."PREC"f\n", u, k2, gsl_ellip_sn (u, 1.0 - k2)); } else if (strcmp (arg, "sci_asn") == 0) { double y, k2; y = atof (pshift ()); k2 = atof (pshift ()); g_print ("sci_asn(%f, %f) = %."PREC"f\n", y, k2, gsl_ellip_asn (y, 1.0 - k2)); } else if (strcmp (arg, "sci_asnc") == 0) { GslComplex y, k2; y.re = atof (pshift ()); y.im = atof (pshift ()); k2.re = atof (pshift ()); k2.im = atof (pshift ()); g_print ("sci_asnc(%s, %s) = %s\n", gsl_complex_str (y), gsl_complex_str (k2), gsl_complex_str (gsl_complex_ellip_asn (y, gsl_complex_sub (gsl_complex (1.0, 0), k2)))); g_print ("asn(%f, %f = %."PREC"f\n", y.re, k2.re, gsl_ellip_asn (y.re, 1.0 - k2.re)); } else if (strcmp (arg, "sin") == 0) { GslComplex phi; phi.re = atof (pshift ()); phi.im = atof (pshift ()); g_print ("sin(%s) = %s\n", gsl_complex_str (phi), gsl_complex_str (gsl_complex_sin (phi))); } else if (strcmp (arg, "cos") == 0) { GslComplex phi; phi.re = atof (pshift ()); phi.im = atof (pshift ()); g_print ("cos(%s) = %s\n", gsl_complex_str (phi), gsl_complex_str (gsl_complex_cos (phi))); } else if (strcmp (arg, "tan") == 0) { GslComplex phi; phi.re = atof (pshift ()); phi.im = atof (pshift ()); g_print ("tan(%s) = %s\n", gsl_complex_str (phi), gsl_complex_str (gsl_complex_tan (phi))); } else if (strcmp (arg, "sinh") == 0) { GslComplex phi; phi.re = atof (pshift ()); phi.im = atof (pshift ()); g_print ("sinh(%s) = %s\n", gsl_complex_str (phi), gsl_complex_str (gsl_complex_sinh (phi))); } else if (strcmp (arg, "cosh") == 0) { GslComplex phi; phi.re = atof (pshift ()); phi.im = atof (pshift ()); g_print ("cosh(%s) = %s\n", gsl_complex_str (phi), gsl_complex_str (gsl_complex_cosh (phi))); } else if (strcmp (arg, "tanh") == 0) { GslComplex phi; phi.re = atof (pshift ()); phi.im = atof (pshift ()); g_print ("tanh(%s) = %s\n", gsl_complex_str (phi), gsl_complex_str (gsl_complex_tanh (phi))); } else if (strcmp (arg, "midi2freq") == 0) { gint note; note = atol (pshift ()); note = CLAMP (note, 0, 128); g_print ("midi2freq(%u) = %f\n", note, gsl_temp_freq (gsl_get_config ()->kammer_freq, note - gsl_get_config ()->midi_kammer_note)); } else if (strcmp (arg, "blp") == 0) { double f, e; order = atoi (pshift ()); order = MAX (order, 1); f = atof (pshift ()); e = atof (pshift ()); f *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_butter_lp (order, f, e, a, b); g_print ("# Lowpass Butterworth filter order=%u freq=%f epsilon(s^2)=%f norm0=%f:\n", order, f, e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "BL"; } else if (strcmp (arg, "bhp") == 0) { double f, e; order = atoi (pshift ()); order = MAX (order, 1); f = atof (pshift ()); e = atof (pshift ()); f *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_butter_hp (order, f, e, a, b); g_print ("# Highpass Butterworth filter order=%u freq=%f epsilon(s^2)=%f norm0=%f:\n", order, f, e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "BH"; } else if (strcmp (arg, "bbp") == 0) { double f1, f2, e; order = atoi (pshift ()); order = MAX (order, 1); f1 = atof (pshift ()); f2 = atof (pshift ()); e = atof (pshift ()); f1 *= GSL_PI / 2.; f2 *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_butter_bp (order, f1, f2, e, a, b); g_print ("# Bandpass Butterworth filter order=%u freq1=%f freq2=%f epsilon(s^2)=%f norm0=%f:\n", order, f1, f2, e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "BP"; } else if (strcmp (arg, "bbs") == 0) { double f1, f2, e; order = atoi (pshift ()); order = MAX (order, 1); f1 = atof (pshift ()); f2 = atof (pshift ()); e = atof (pshift ()); f1 *= GSL_PI / 2.; f2 *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_butter_bs (order, f1, f2, e, a, b); g_print ("# Bandstop Butterworth filter order=%u freq1=%f freq2=%f epsilon(s^2)=%f norm0=%f:\n", order, f1, f2, e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "BS"; } else if (strcmp (arg, "t1l") == 0) { double f, e; order = atoi (pshift ()); order = MAX (order, 1); f = atof (pshift ()); e = atof (pshift ()); f *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_tscheb1_lp (order, f, e, a, b); g_print ("# Lowpass Tschebyscheff Type1 order=%u freq=%f epsilon(s^2)=%f norm0=%f:\n", order, f, e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "T1L"; } else if (strcmp (arg, "t1h") == 0) { double f, e; order = atoi (pshift ()); order = MAX (order, 1); f = atof (pshift ()); e = atof (pshift ()); f *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_tscheb1_hp (order, f, e, a, b); g_print ("# Highpass Tschebyscheff Type1 order=%u freq=%f epsilon(s^2)=%f norm0=%f:\n", order, f, e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "T1H"; } else if (strcmp (arg, "t1s") == 0) { double fc, fr, e; order = atoi (pshift ()); order = MAX (order, 1); fc = atof (pshift ()); fr = atof (pshift ()); e = atof (pshift ()); fc *= GSL_PI / 2.; fr *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_tscheb1_bs (order, fc, fr, e, a, b); g_print ("# Bandstop Tschebyscheff Type1 order=%u freq_c=%f freq_r=%f epsilon(s^2)=%f norm=%f:\n", order, fc, fr, e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "T1S"; } else if (strcmp (arg, "t1p") == 0) { double fc, fr, e; order = atoi (pshift ()); order = MAX (order, 1); fc = atof (pshift ()); fr = atof (pshift ()); e = atof (pshift ()); fc *= GSL_PI / 2.; fr *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_tscheb1_bp (order, fc, fr, e, a, b); g_print ("# Bandpass Tschebyscheff Type1 order=%u freq_c=%f freq_r=%f epsilon(s^2)=%f norm=%f:\n", order, fc, fr, e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "T1P"; } else if (strcmp (arg, "t2l") == 0) { double f, st, e; order = atoi (pshift ()); order = MAX (order, 1); f = atof (pshift ()); st = atof (pshift ()); e = atof (pshift ()); f *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_tscheb2_lp (order, f, st, e, a, b); g_print ("# Lowpass Tschebyscheff Type2 order=%u freq=%f steepness=%f (%f) epsilon(s^2)=%f norm=%f:\n", order, f, st, f * (1.+st), e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "T2L"; } else if (strcmp (arg, "t2h") == 0) { double f, st, e; order = atoi (pshift ()); order = MAX (order, 1); f = atof (pshift ()); st = atof (pshift ()); e = atof (pshift ()); f *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_tscheb2_hp (order, f, st, e, a, b); g_print ("# Highpass Tschebyscheff Type2 order=%u freq=%f steepness=%f (%f, %f) epsilon(s^2)=%f norm=%f:\n", order, f, st, GSL_PI - f, (GSL_PI - f) * (1.+st), e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "T2H"; } else if (strcmp (arg, "t2p") == 0) { double f1, f2, st, e; order = atoi (pshift ()); order = MAX (order, 1); f1 = atof (pshift ()); f2 = atof (pshift ()); st = atof (pshift ()); e = atof (pshift ()); f1 *= GSL_PI / 2.; f2 *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_tscheb2_bp (order, f1, f2, st, e, a, b); g_print ("# Bandpass Tschebyscheff Type2 order=%u freq1=%f freq2=%f steepness=%f epsilon(s^2)=%f norm=%f:\n", order, f1, f2, st, e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "T2P"; } else if (strcmp (arg, "t2s") == 0) { double f1, f2, st, e; order = atoi (pshift ()); order = MAX (order, 1); f1 = atof (pshift ()); f2 = atof (pshift ()); st = atof (pshift ()); e = atof (pshift ()); f1 *= GSL_PI / 2.; f2 *= GSL_PI / 2.; a = g_new (gdouble, order + 1); b = g_new (gdouble, order + 1); gsl_filter_tscheb2_bs (order, f1, f2, st, e, a, b); g_print ("# Bandstop Tschebyscheff Type2 order=%u freq1=%f freq2=%f steepness=%f epsilon(s^2)=%f norm=%f:\n", order, f1, f2, st, e, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); filter_label = "T2S"; } else if (strcmp (arg, "scan") == 0) { filter_mode = FILTER_SCAN; } else if (strcmp (arg, "fir") == 0) { unsigned int iorder = atoi (pshift ()); unsigned int n_points = 0; double *freq = g_newa (double, argc / 2 + 1); double *value = g_newa (double, argc / 2 + 1); double *a = g_newa (double, iorder); const char *f, *v; do { f = pshift (); v = pshift (); if (f[0] && v[0]) { freq[n_points] = atof (f) * GSL_PI; value[n_points] = atof (v); n_points++; } } while (f[0] && v[0]); gsl_filter_fir_approx (iorder, a, n_points, freq, value); g_print ("FIR%u(z)=%s\n", iorder, gsl_poly_str (iorder, a, "z")); } else if (strncmp (arg, "poly", 4) == 0) { guint order; arg = arg + 4; order = 2; { double a[100] = { 1, 2, 1 }, b[100] = { 1, -3./2., 0.5 }; g_print ("# Test order=%u norm=%f:\n", order, gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1)); g_print ("H%u(z)=%s/%s\n", order, gsl_poly_str (order, a, "z"), gsl_poly_str (order, b, "z")); if (*arg) { GslComplex root, roots[100]; guint i; if (*arg == 'r') { g_print ("#roots:\n"); gsl_poly_complex_roots (order, a, roots); for (i = 0; i < order; i++) { root = gsl_complex_div (gsl_complex (1, 0), roots[i]); g_print ("%+.14f %+.14f # %.14f\n", root.re, root.im, gsl_complex_abs (root)); } } if (*arg == 'p') { g_print ("#poles:\n"); gsl_poly_complex_roots (order, b, roots); for (i = 0; i < order; i++) { root = gsl_complex_div (gsl_complex (1, 0), roots[i]); g_print ("%+.14f %+.14f # %.14f\n", root.re, root.im, gsl_complex_abs (root)); } } } } } else usage (); if (a && b) { gdouble freq; if (filter_mode == FILTER_SCAN) { freq = 0.001; while (freq < 3.14) { g_print ("%f %.20f\n", freq, gsl_filter_sine_scan (order, a, b, freq, MAX((int)(1000.0/freq),10000))); freq = MIN (freq * 1.1, freq + 0.01); } } else if (filter_mode == FILTER_GNUPLOT) { g_print ("%s%u(z)=%s/%s\n", filter_label, order, gsl_poly_str (order, a, "z"), gsl_poly_str (order, b, "z")); } else g_error ("unknown filter_mode"); g_free (a); g_free (b); } arg = shift (); if (arg) goto restart; return 0; } static void usage (void) { g_print ("usage: gsltests {test} [args...]\n"); g_print ("tests:\n"); g_print (" wave-scan scan a wave file for waves\n"); g_print (" file-test test file properties\n"); g_print (" rf Carlson's elliptic integral of the first kind\n"); g_print (" F Legendre elliptic integral of the 1st kind\n"); g_print (" sn Jacobian elliptic function sn()\n"); g_print (" asn elliptic integral, inverse sn()\n"); g_print (" sin complex sine\n"); g_print (" cos complex cosine\n"); g_print (" tan complex tangent\n"); g_print (" sinh complex hyperbolic sine\n"); g_print (" cosh complex hyperbolic cosine\n"); g_print (" tanh complex hyperbolic tangent\n"); g_print (" midi2freq convert midinote into oscilaltor frequency\n"); g_print (" snc sn() for complex numbers\n"); g_print (" asnc asn() for complex numbers\n"); g_print (" sci_sn scilab version of sn()\n"); g_print (" sci_asn scilab version of asn()\n"); g_print (" sci_snc scilab version of snc()\n"); g_print (" sci_asnc scilab version of asnc()\n"); g_print (" blp butterworth lowpass filter\n"); g_print (" bhp butterworth higpass filter\n"); g_print (" bbp butterworth bandpass filter\n"); g_print (" t1l type1 tschebyscheff lowpass filter\n"); g_print (" t1h type1 tschebyscheff highpass filter\n"); g_print (" t1s type1 tschebyscheff bandstop filter\n"); g_print (" t1p type1 tschebyscheff bandpass filter\n"); g_print (" t2l type2 tschebyscheff lowpass filter\n"); g_print (" t2h type2 tschebyscheff highpass filter\n"); g_print (" fir ... fir approximation\n"); g_print (" scan blp scan butterworth lowpass filter\n"); g_print (" poly | polyr | polyp polynom test (+roots or +poles)\n"); exit (1); }