r3968 - trunk/bse



Author: stw
Date: 2006-10-15 15:34:06 -0400 (Sun, 15 Oct 2006)
New Revision: 3968

Modified:
   trunk/bse/ChangeLog
   trunk/bse/gslfilter.c
Log:
Sun Oct 15 20:58:57 2006  Stefan Westerfeld  <stefan space twc de>

	* gslfilter.c: Made implementation of gsl_filter_sine_scan() more
	reliable by using two phase shifted signals (see comment in the
	implementation).


Modified: trunk/bse/ChangeLog
===================================================================
--- trunk/bse/ChangeLog	2006-10-12 20:33:39 UTC (rev 3967)
+++ trunk/bse/ChangeLog	2006-10-15 19:34:06 UTC (rev 3968)
@@ -1,3 +1,9 @@
+Sun Oct 15 20:58:57 2006  Stefan Westerfeld  <stefan space twc de>
+
+	* gslfilter.c: Made implementation of gsl_filter_sine_scan() more
+	reliable by using two phase shifted signals (see comment in the
+	implementation).
+
 Thu Oct 12 22:30:46 2006  Stefan Westerfeld  <stefan space twc de>
 
 	* bsedatahandle-resample.cc: Use the newly introduced

Modified: trunk/bse/gslfilter.c
===================================================================
--- trunk/bse/gslfilter.c	2006-10-12 20:33:39 UTC (rev 3967)
+++ trunk/bse/gslfilter.c	2006-10-15 19:34:06 UTC (rev 3968)
@@ -1339,22 +1339,33 @@
 		      gdouble freq,
 		      guint n_values)
 {
-  gfloat x[SINE_SCAN_SIZE], y[SINE_SCAN_SIZE];
+  gfloat x_r[SINE_SCAN_SIZE], x_i[SINE_SCAN_SIZE];
+  gfloat y_r[SINE_SCAN_SIZE], y_i[SINE_SCAN_SIZE];
   gdouble pos = 0.0;
   gdouble result = 0.0;
-  GslIIRFilter filter;
-  gdouble *filter_state;
+  GslIIRFilter filter_r;
+  GslIIRFilter filter_i;
+  gdouble *filter_state_r;
+  gdouble *filter_state_i;
   guint scan_start = n_values / 2;
   
   g_return_val_if_fail (order > 0, 0.0);
   g_return_val_if_fail (a != NULL, 0.0);
   g_return_val_if_fail (b != NULL, 0.0);
-  g_return_val_if_fail (freq > 0 && freq < PI, 0.0);
+  g_return_val_if_fail (freq >= 0 && freq < PI, 0.0);
   g_return_val_if_fail (n_values > 0, 0.0);
   
-  filter_state = g_newa (double, (order + 1) * 4);
-  gsl_iir_filter_setup (&filter, order, a, b, filter_state);
-  
+  filter_state_r = g_newa (double, (order + 1) * 4);
+  filter_state_i = g_newa (double, (order + 1) * 4);
+  gsl_iir_filter_setup (&filter_r, order, a, b, filter_state_r);
+  gsl_iir_filter_setup (&filter_i, order, a, b, filter_state_i);
+
+  /* The implementation filters two phase shifted signals; by doing so, it
+   * actually computes the frequency response of the filter for a complex
+   * signal. The advantage is that for each sample the absolute value can be
+   * determined exactly as complex absolute value (whereas for a single sine
+   * signal, the absolute value oscillates).
+   */
   while (n_values)
     {
       guint todo = MIN (n_values, SINE_SCAN_SIZE);
@@ -1362,15 +1373,17 @@
       
       for (i = 0; i < todo; i++)
 	{
-	  x[i] = sin (pos);
+	  x_r[i] = cos (pos);
+	  x_i[i] = sin (pos);
 	  pos += freq;
 	}
       
-      gsl_iir_filter_eval (&filter, SINE_SCAN_SIZE, x, y);
+      gsl_iir_filter_eval (&filter_r, SINE_SCAN_SIZE, x_r, y_r);
+      gsl_iir_filter_eval (&filter_i, SINE_SCAN_SIZE, x_i, y_i);
       
       for (i = 0; i < todo; i++)
         if (n_values - i < scan_start)
-	  result = MAX (y[i], result);
+	  result = MAX (bse_complex_abs (bse_complex (y_r[i], y_i[i])), result);
       
       n_values -= todo;
     }




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]