r3965 - in trunk/bse: . tests



Author: stw
Date: 2006-10-12 16:11:29 -0400 (Thu, 12 Oct 2006)
New Revision: 3965

Modified:
   trunk/bse/ChangeLog
   trunk/bse/bseresampler.cc
   trunk/bse/bseresampler.hh
   trunk/bse/bseresamplerimpl.hh
   trunk/bse/tests/resamplehandle.cc
Log:
Thu Oct 12 21:48:54 2006  Stefan Westerfeld  <stefan space twc de>

	* bseresampler.hh:
	* bseresampler.cc:
	* bseresamplerimpl.hh: Added a virtual function Resampler2::delay(),
	which can be used for compensation of the resampler introduced delay.
	Provide C API wrapper for the function: bse_resampler2_delay().

	* tests/resamplehandle.cc: Test the delay compensation function.
	Fix a buglet in another test (comparing signals needs fabs()).


Modified: trunk/bse/ChangeLog
===================================================================
--- trunk/bse/ChangeLog	2006-10-12 18:45:54 UTC (rev 3964)
+++ trunk/bse/ChangeLog	2006-10-12 20:11:29 UTC (rev 3965)
@@ -1,3 +1,14 @@
+Thu Oct 12 21:48:54 2006  Stefan Westerfeld  <stefan space twc de>
+
+	* bseresampler.hh:
+	* bseresampler.cc:
+	* bseresamplerimpl.hh: Added a virtual function Resampler2::delay(),
+	which can be used for compensation of the resampler introduced delay.
+	Provide C API wrapper for the function: bse_resampler2_delay().
+
+	* tests/resamplehandle.cc: Test the delay compensation function.
+	Fix a buglet in another test (comparing signals needs fabs()).
+
 Thu Oct 12 16:54:42 2006  Stefan Westerfeld  <stefan space twc de>
 
 	* gslfft.h: Improved documentation on FFT normalization.

Modified: trunk/bse/bseresampler.cc
===================================================================
--- trunk/bse/bseresampler.cc	2006-10-12 18:45:54 UTC (rev 3964)
+++ trunk/bse/bseresampler.cc	2006-10-12 20:11:29 UTC (rev 3965)
@@ -295,3 +295,9 @@
 {
   return reinterpret_cast<Bse::Resampler::Resampler2 *> (resampler)->order();
 }
+
+double
+bse_resampler2_delay (BseResampler2 *resampler)
+{
+  return reinterpret_cast<Bse::Resampler::Resampler2 *> (resampler)->delay();
+}

Modified: trunk/bse/bseresampler.hh
===================================================================
--- trunk/bse/bseresampler.hh	2006-10-12 18:45:54 UTC (rev 3964)
+++ trunk/bse/bseresampler.hh	2006-10-12 20:11:29 UTC (rev 3965)
@@ -48,6 +48,7 @@
                                              unsigned int           n_input_samples,
 					     float                 *output);
 guint	       bse_resampler2_order         (BseResampler2         *resampler);
+double	       bse_resampler2_delay         (BseResampler2         *resampler);
 
 G_END_DECLS
 
@@ -79,6 +80,18 @@
    * return FIR filter order
    */
   virtual guint	      order() const = 0;
+  /**
+   * Return the delay introduced by the resampler. This delay is guaranteed to
+   * be >= 0.0, and for factor 2 resampling always a multiple of 0.5.
+   *
+   * The return value can also be thought of the index in the output signal,
+   * where the first input sample can be found.
+   *
+   * Beware of fractional delays, for instance for downsampling, a delay() of
+   * 10.5 means that the first input sample would be found by interpolating
+   * output[10] and output[11], and the second input sample equates output[11].
+   */
+  virtual double      delay() const = 0;
 protected:
   static const double halfband_fir_48db_coeffs[16];
   static const double halfband_fir_72db_coeffs[24];

Modified: trunk/bse/bseresamplerimpl.hh
===================================================================
--- trunk/bse/bseresamplerimpl.hh	2006-10-12 18:45:54 UTC (rev 3964)
+++ trunk/bse/bseresamplerimpl.hh	2006-10-12 20:11:29 UTC (rev 3965)
@@ -397,6 +397,11 @@
   {
     return ORDER;
   }
+  double
+  delay() const
+  {
+    return order() + 2;
+  }
 };
 
 /**
@@ -569,6 +574,11 @@
   {
     return ORDER;
   }
+  double
+  delay() const
+  {
+    return order() / 2 + 0.5;
+  }
 };
 
 template<bool USE_SSE> Resampler2*

Modified: trunk/bse/tests/resamplehandle.cc
===================================================================
--- trunk/bse/tests/resamplehandle.cc	2006-10-12 18:45:54 UTC (rev 3964)
+++ trunk/bse/tests/resamplehandle.cc	2006-10-12 20:11:29 UTC (rev 3965)
@@ -259,7 +259,7 @@
     {
       double expected = sin ((i - delay) * 220 * 2 * M_PI / 44100)
 	              * bse_window_blackman ((double) ((i - delay) * 2 - OUTPUT_SIZE) / OUTPUT_SIZE);
-      error = MAX (error, out[i] - expected);
+      error = MAX (error, fabs (out[i] - expected));
     }
 
   double error_db = bse_db_from_factor (error, -200);
@@ -271,6 +271,83 @@
   TDONE();
 }
 
+static void
+test_delay_compensation (const char *run_type)
+{
+  struct TestParameters {
+    double error_db;
+    BseResampler2Mode mode;
+    BseResampler2Precision precision;
+  } params[] =
+  {
+    { 200, BSE_RESAMPLER2_MODE_UPSAMPLE, BSE_RESAMPLER2_PREC_48DB },
+    { 200, BSE_RESAMPLER2_MODE_UPSAMPLE, BSE_RESAMPLER2_PREC_72DB },
+    { 200, BSE_RESAMPLER2_MODE_UPSAMPLE, BSE_RESAMPLER2_PREC_96DB },
+    { 200, BSE_RESAMPLER2_MODE_UPSAMPLE, BSE_RESAMPLER2_PREC_120DB },
+    { 200, BSE_RESAMPLER2_MODE_UPSAMPLE, BSE_RESAMPLER2_PREC_144DB },
+    { 48,  BSE_RESAMPLER2_MODE_DOWNSAMPLE, BSE_RESAMPLER2_PREC_48DB },
+    { 67,  BSE_RESAMPLER2_MODE_DOWNSAMPLE, BSE_RESAMPLER2_PREC_72DB },
+    { 96,  BSE_RESAMPLER2_MODE_DOWNSAMPLE, BSE_RESAMPLER2_PREC_96DB },
+    { 120, BSE_RESAMPLER2_MODE_DOWNSAMPLE, BSE_RESAMPLER2_PREC_120DB },
+    { 134, BSE_RESAMPLER2_MODE_DOWNSAMPLE, BSE_RESAMPLER2_PREC_144DB },
+    { -1, }
+  };
+
+  using Bse::Resampler::Resampler2;
+  TSTART ("Resampler Delay Compensation (%s)", run_type);
+
+  for (guint p = 0; params[p].error_db > 0; p++)
+    {
+      /* setup test signal and empty output signal space */
+      const int INPUT_SIZE = 44100 * 4, OUTPUT_SIZE = INPUT_SIZE * 2;
+
+      vector<float> in (INPUT_SIZE);
+      vector<float> out (OUTPUT_SIZE);
+
+      generate_test_signal (in, INPUT_SIZE, 44100, 440);
+
+      /* up/downsample test signal */
+      Resampler2 *resampler = Resampler2::create (params[p].mode,
+                                                  params[p].precision);
+      resampler->process_block (&in[0], INPUT_SIZE, &out[0]);
+
+      /* setup increments for comparision loop */
+      size_t iinc = 1, jinc = 1;
+      if (params[p].mode == BSE_RESAMPLER2_MODE_UPSAMPLE)
+	jinc = 2;
+      else
+	iinc = 2;
+
+      /* compensate resampler delay by incrementing comparision start offset */
+      double delay = resampler->delay();
+      size_t i = 0, j = (int) round (delay * 2);
+      if (j % 2)
+	{
+	  /* implement half a sample delay (for downsampling only) */
+	  g_assert (params[p].mode == BSE_RESAMPLER2_MODE_DOWNSAMPLE);
+	  i++;
+	  j += 2;
+	}
+      j /= 2;
+
+      /* actually compare source and resampled signal (one with a stepping of 2) */
+      double error = 0;
+      while (i < in.size() && j < out.size())
+	{
+	  error = MAX (error, fabs (out[j] - in[i]));
+	  i += iinc; j += jinc;
+	}
+
+      delete resampler;
+
+      /* check error against bound */
+      double error_db = bse_db_from_factor (error, -250);
+      TPRINT ("Resampler Delay Compensation delta: %f\n", error_db);
+      TASSERT (error_db < -params[p].error_db);
+    }
+  TDONE();
+}
+
 int
 main (int   argc,
       char *argv[])
@@ -278,6 +355,7 @@
   sfi_init_test (&argc, &argv, NULL);
   
   test_c_api ("FPU");
+  test_delay_compensation ("FPU");
   run_tests ("FPU");
 
   /* load plugins */
@@ -291,6 +369,7 @@
     return 0;   /* nothing changed */
 
   test_c_api ("SSE");
+  test_delay_compensation ("SSE");
   run_tests ("SSE");
 
   return 0;




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