r3935 - in trunk/bse: . tests



Author: stw
Date: 2006-10-05 11:52:43 -0400 (Thu, 05 Oct 2006)
New Revision: 3935

Modified:
   trunk/bse/ChangeLog
   trunk/bse/bsedatahandle-resample.cc
   trunk/bse/gsldatahandle.h
   trunk/bse/tests/resamplehandle.cc
Log:
Thu Oct  5 17:39:50 2006  Stefan Westerfeld  <stefan space twc de>

	* gsldatahandle.h:
	* bsedatahandle-resample.cc: Implemented factor 2 downsampling
	datahandle.  Moved common code into a base class for both datahandles.

	* tests/resamplehandle.cc: Test downsampling datahandle.


Modified: trunk/bse/ChangeLog
===================================================================
--- trunk/bse/ChangeLog	2006-10-05 14:51:03 UTC (rev 3934)
+++ trunk/bse/ChangeLog	2006-10-05 15:52:43 UTC (rev 3935)
@@ -1,3 +1,11 @@
+Thu Oct  5 17:39:50 2006  Stefan Westerfeld  <stefan space twc de>
+
+	* gsldatahandle.h:
+	* bsedatahandle-resample.cc: Implemented factor 2 downsampling
+	datahandle.  Moved common code into a base class for both datahandles.
+
+	* tests/resamplehandle.cc: Test downsampling datahandle.
+
 Sat Sep 30 21:36:39 2006  Tim Janik  <timj gtk org>
 
 	* bseautodoc.c: fixed -p and -s not taking effect.

Modified: trunk/bse/bsedatahandle-resample.cc
===================================================================
--- trunk/bse/bsedatahandle-resample.cc	2006-10-05 14:51:03 UTC (rev 3934)
+++ trunk/bse/bsedatahandle-resample.cc	2006-10-05 15:52:43 UTC (rev 3935)
@@ -26,30 +26,29 @@
 using Resampler::Resampler2;
 using std::vector;
 
-class DataHandleUpsample2
+class DataHandleResample2;
+
+struct CDataHandleResample2 : public GslDataHandle
 {
-  GslDataHandle         m_dhandle;
+  // back pointer to get casting right, even in presence of C++ vtable:
+  DataHandleResample2* cxx_dh;
+};
+
+class DataHandleResample2
+{
+protected:
+  CDataHandleResample2	m_dhandle;
   GslDataHandle	       *m_src_handle;
   int                   m_precision_bits;
-  vector<Resampler2 *>  m_upsamplers;
+  vector<Resampler2 *>  m_resamplers;
   int64			m_pcm_frame;
   vector<float>		m_pcm_data;
   int64			m_frame_size;
   int64                 m_filter_delay;
   int64                 m_filter_order;
-  bool   		m_init_ok;
+  bool			m_init_ok;
 
-  /* private destructor: (use reference counting instead) */
-  ~DataHandleUpsample2()
-  {
-    if (m_init_ok)
-      {
-	gsl_data_handle_unref (m_src_handle);
-	gsl_data_handle_common_free (&m_dhandle);
-      }
-  }
-public:
-  DataHandleUpsample2 (GslDataHandle *src_handle,
+  DataHandleResample2 (GslDataHandle *src_handle,
                        int            precision_bits) :
     m_src_handle (src_handle),
     m_precision_bits (precision_bits),
@@ -60,60 +59,24 @@
     m_init_ok (false)
   {
     g_return_if_fail (src_handle != NULL);
- 
+
     memset (&m_dhandle, 0, sizeof (m_dhandle));
-
     m_init_ok = gsl_data_handle_common_init (&m_dhandle, NULL);
     if (m_init_ok)
-      {
-	m_dhandle.name = g_strconcat (m_src_handle->name, "// #upsample2 /", NULL);
-	gsl_data_handle_ref (m_src_handle);
-      }
+      gsl_data_handle_ref (m_src_handle);
   }
-  BseErrorType
-  open (GslDataHandleSetup *setup)
+
+  /* protected destructor: (use reference counting instead) */
+  virtual
+  ~DataHandleResample2()
   {
-    BseErrorType error = gsl_data_handle_open (m_src_handle);
-    if (error != BSE_ERROR_NONE)
-      return error;
-
-    /* !not! m_dhandle.setup; the framework magically ensures that *m_dhandle.setup
-     * is initialized by whatever we write into *setup if open is successful
-     */
-    *setup = m_src_handle->setup; /* copies setup.xinfos by pointer */
-    setup->mix_freq *= 2.0;
-    setup->n_values *= 2;
-
-    m_frame_size = 1024 * setup->n_channels;
-    m_pcm_frame = -2;
-    m_pcm_data.resize (m_frame_size);
-
-    for (guint i = 0; i < setup->n_channels; i++)
+    if (m_init_ok)
       {
-	BseResampler2Precision precision = static_cast<BseResampler2Precision> (m_precision_bits);
-	Resampler2 *resampler = Resampler2::create (BSE_RESAMPLER2_MODE_UPSAMPLE, precision);
-	g_assert (resampler); /* FIXME: better error handling */
-
-	m_upsamplers.push_back (resampler);
-	m_filter_order = resampler->order();
-
-	g_assert (m_filter_order % 2 == 0);
-	m_filter_delay = m_filter_order / 2 + 1;
+	gsl_data_handle_unref (m_src_handle);
+	gsl_data_handle_common_free (&m_dhandle);
       }
-    return BSE_ERROR_NONE;
   }
-  void
-  close()
-  {
-    for (guint i = 0; i < m_dhandle.setup.n_channels; i++)
-      delete m_upsamplers[i];
 
-    m_upsamplers.clear();
-    m_pcm_data.clear();
-    
-    m_dhandle.setup.xinfos = NULL;	/* cleanup pointer reference */
-    gsl_data_handle_close (m_src_handle);
-  }
   int64
   src_read (int64   voffset,
 	    int64   n_values,
@@ -171,65 +134,65 @@
       for (int64 v = ch; v < n_values; v += n_channels)
 	dest[v] = *src++;
   }
-  int64
-  prepare_filter_history (int64 frame)
-  {
-    const int64 n_channels = m_dhandle.setup.n_channels;
-    const int64 n_input_samples = m_filter_order;
 
-    float input_interleaved[n_input_samples * n_channels];
-    float input[n_input_samples * n_channels];
+  /* implemented by upsampling and downsampling datahandle */
+  virtual BseResampler2Mode mode	() = 0;
+  virtual int64		    read_frame  (int64 frame) = 0;
 
-    int64 l = src_read (frame * m_frame_size / 2 - n_input_samples * n_channels,
-	                n_input_samples * n_channels, input_interleaved);
-    if (l < 0)
-      return l; /* pass on errors */
+public:
+  BseErrorType
+  open (GslDataHandleSetup *setup)
+  {
+    BseErrorType error = gsl_data_handle_open (m_src_handle);
+    if (error != BSE_ERROR_NONE)
+      return error;
 
-    deinterleave (input_interleaved, input, n_input_samples * m_dhandle.setup.n_channels);
-
-    for (guint ch = 0; ch < m_dhandle.setup.n_channels; ch++)
-      {
-	/* we don't need the output, this is just for filling the filter history */
-	float output[n_input_samples * 2];
-
-	m_upsamplers[ch]->process_block (input + ch * n_input_samples, n_input_samples, output);
-      }
-    return 1;
-  }
-  int64
-  read_frame (int64 frame)
-  {
-    /*
-     * if we're seeking (not reading data linearily), we need to reinitialize
-     * the filter history with new values
+    /* !not! m_dhandle.setup; the framework magically ensures that *m_dhandle.setup
+     * is initialized by whatever we write into *setup if open is successful
      */
-    if (frame != m_pcm_frame + 1)
+    *setup = m_src_handle->setup; /* copies setup.xinfos by pointer */
+    switch (mode())
       {
-	int64 l = prepare_filter_history (frame);
-	if (l < 0)
-	  return l; /* pass on errors */
+      case BSE_RESAMPLER2_MODE_UPSAMPLE:    setup->mix_freq *= 2.0;
+					    setup->n_values *= 2;
+					    break;
+      case BSE_RESAMPLER2_MODE_DOWNSAMPLE:  setup->mix_freq /= 2.0;
+					    setup->n_values = (setup->n_values + 1) / 2;
+					    break;
+      default:				    g_assert_not_reached();
       }
+    
+    m_frame_size = 1024 * setup->n_channels;
+    m_pcm_frame = -2;
+    m_pcm_data.resize (m_frame_size);
 
-    float input_interleaved[m_frame_size / 2];
-    float input[m_frame_size / 2];
-    float output[m_frame_size];
-
-    int64 l = src_read (frame * m_frame_size / 2, m_frame_size / 2, input_interleaved);
-    if (l < 0)
-      return l; /* pass on errors */
-
-    deinterleave (input_interleaved, input, m_frame_size / 2);
-    for (guint ch = 0; ch < m_dhandle.setup.n_channels; ch++)
+    for (guint i = 0; i < setup->n_channels; i++)
       {
-	const int64 output_per_channel = m_frame_size / m_dhandle.setup.n_channels;
-	const int64 input_per_channel = output_per_channel / 2;
+	BseResampler2Precision precision = static_cast<BseResampler2Precision> (m_precision_bits);
+	Resampler2 *resampler = Resampler2::create (mode(), precision);
+	g_assert (resampler); /* FIXME: better error handling */
 
-	m_upsamplers[ch]->process_block (input + ch * input_per_channel, input_per_channel, output + ch * output_per_channel);
+	m_resamplers.push_back (resampler);
+	m_filter_order = resampler->order();
+	
+	g_assert (m_filter_order % 2 == 0);
+	m_filter_delay = mode() == BSE_RESAMPLER2_MODE_UPSAMPLE ?
+	                 m_filter_order / 2 + 1 :
+			 m_filter_order + 1;
       }
-    interleave (output, &m_pcm_data[0], m_frame_size);
+    return BSE_ERROR_NONE;
+  }
+  void
+  close()
+  {
+    for (guint i = 0; i < m_dhandle.setup.n_channels; i++)
+      delete m_resamplers[i];
 
-    m_pcm_frame = frame;
-    return 1;
+    m_resamplers.clear();
+    m_pcm_data.clear();
+    
+    m_dhandle.setup.xinfos = NULL;	/* cleanup pointer reference */
+    gsl_data_handle_close (m_src_handle);
   }
   int64
   read (int64  voffset,
@@ -255,12 +218,37 @@
     return n_values;
   }
 
+  static GslDataHandle*
+  dh_create (DataHandleResample2 *cxx_dh)
+  {
+    static GslDataHandleFuncs dh_vtable =
+    {
+      dh_open,
+      dh_read,
+      dh_close,
+      NULL,
+      dh_destroy,
+    };
+    if (cxx_dh->m_init_ok)
+      {
+	cxx_dh->m_dhandle.vtable = &dh_vtable;
+	cxx_dh->m_dhandle.cxx_dh = cxx_dh;	/* make casts work, later on */
+	return &cxx_dh->m_dhandle;
+      }
+    else
+      {
+	delete cxx_dh;
+	return NULL;
+      }
+  }
+
 private:
 /* for the "C" API (vtable) */
-  static DataHandleUpsample2*
+  static DataHandleResample2*
   dh_cast (GslDataHandle *dhandle)
   {
-    return reinterpret_cast<DataHandleUpsample2 *> (dhandle);
+    return static_cast<CDataHandleResample2 *> (dhandle)->cxx_dh;
+    //return reinterpret_cast<DataHandleResample2 *> (dhandle);
   }
   static BseErrorType
   dh_open (GslDataHandle *dhandle, GslDataHandleSetup *setup)
@@ -285,39 +273,176 @@
   {
     return dh_cast (dhandle)->read (voffset, n_values, values);
   }
+};
 
+class DataHandleUpsample2 : public DataHandleResample2
+{
 public:
-  static GslDataHandle*
-  dh_create (GslDataHandle *src_handle,
-	     int            precision_bits)
+  DataHandleUpsample2 (GslDataHandle *src_handle,
+                       int            precision_bits) :
+    DataHandleResample2 (src_handle, precision_bits)
   {
-    static GslDataHandleFuncs dh_vtable =
-    {
-      dh_open,
-      dh_read,
-      dh_close,
-      NULL,
-      dh_destroy,
-    };
-    DataHandleUpsample2 *dhandle = new DataHandleUpsample2 (src_handle, precision_bits);
-    if (dhandle->m_init_ok)
+    if (m_init_ok)
+      m_dhandle.name = g_strconcat (m_src_handle->name, "// #upsample2 /", NULL);
+  }
+  BseResampler2Mode
+  mode()
+  {
+    return BSE_RESAMPLER2_MODE_UPSAMPLE;
+  }
+  int64
+  prepare_filter_history (int64 frame)
+  {
+    const int64 n_channels = m_dhandle.setup.n_channels;
+    const int64 n_input_samples = m_filter_order;
+
+    float input_interleaved[n_input_samples * n_channels];
+    float input[n_input_samples * n_channels];
+
+    int64 l = src_read (frame * m_frame_size / 2 - n_input_samples * n_channels,
+	                n_input_samples * n_channels, input_interleaved);
+    if (l < 0)
+      return l; /* pass on errors */
+
+    deinterleave (input_interleaved, input, n_input_samples * m_dhandle.setup.n_channels);
+
+    for (guint ch = 0; ch < m_dhandle.setup.n_channels; ch++)
       {
-	dhandle->m_dhandle.vtable = &dh_vtable;
-	return &dhandle->m_dhandle;
+	/* we don't need the output, this is just for filling the filter history */
+	float output[n_input_samples * 2];
+
+	m_resamplers[ch]->process_block (input + ch * n_input_samples, n_input_samples, output);
       }
-    else
+    return 1;
+  }
+  int64
+  read_frame (int64 frame)
+  {
+    /*
+     * if we're seeking (not reading data linearily), we need to reinitialize
+     * the filter history with new values
+     */
+    if (frame != m_pcm_frame + 1)
       {
-	delete dhandle;
-	return NULL;
+	int64 l = prepare_filter_history (frame);
+	if (l < 0)
+	  return l; /* pass on errors */
       }
+
+    float input_interleaved[m_frame_size / 2];
+    float input[m_frame_size / 2];
+    float output[m_frame_size];
+
+    int64 l = src_read (frame * m_frame_size / 2, m_frame_size / 2, input_interleaved);
+    if (l < 0)
+      return l; /* pass on errors */
+
+    deinterleave (input_interleaved, input, m_frame_size / 2);
+    for (guint ch = 0; ch < m_dhandle.setup.n_channels; ch++)
+      {
+	const int64 output_per_channel = m_frame_size / m_dhandle.setup.n_channels;
+	const int64 input_per_channel = output_per_channel / 2;
+
+	m_resamplers[ch]->process_block (input + ch * input_per_channel, input_per_channel, output + ch * output_per_channel);
+      }
+    interleave (output, &m_pcm_data[0], m_frame_size);
+
+    m_pcm_frame = frame;
+    return 1;
   }
 };
 
+class DataHandleDownsample2 : public DataHandleResample2
+{
+public:
+  DataHandleDownsample2 (GslDataHandle *src_handle,
+			 int            precision_bits) :
+    DataHandleResample2 (src_handle, precision_bits)
+  {
+  }
+  BseResampler2Mode
+  mode()
+  {
+    return BSE_RESAMPLER2_MODE_DOWNSAMPLE;
+  }
+  int64
+  prepare_filter_history (int64 frame)
+  {
+    const int64 n_channels = m_dhandle.setup.n_channels;
+    const int64 n_input_samples = m_filter_order * 2;
+
+    float input_interleaved[n_input_samples * n_channels];
+    float input[n_input_samples * n_channels];
+
+    int64 l = src_read (frame * m_frame_size * 2 - n_input_samples * n_channels,
+	                n_input_samples * n_channels, input_interleaved);
+    if (l < 0)
+      return l; /* pass on errors */
+
+    deinterleave (input_interleaved, input, n_input_samples * m_dhandle.setup.n_channels);
+
+    for (guint ch = 0; ch < m_dhandle.setup.n_channels; ch++)
+      {
+	/* we don't need the output, this is just for filling the filter history */
+	float output[n_input_samples / 2];
+
+	m_resamplers[ch]->process_block (input + ch * n_input_samples, n_input_samples, output);
+      }
+    return 1;
+  }
+  int64
+  read_frame (int64 frame)
+  {
+    /*
+     * if we're seeking (not reading data linearily), we need to reinitialize
+     * the filter history with new values
+     */
+    if (frame != m_pcm_frame + 1)
+      {
+	int64 l = prepare_filter_history (frame);
+	if (l < 0)
+	  return l; /* pass on errors */
+      }
+
+    float input_interleaved[m_frame_size * 2];
+    float input[m_frame_size * 2];
+    float output[m_frame_size];
+
+    int64 l = src_read (frame * m_frame_size * 2, m_frame_size * 2, input_interleaved);
+    if (l < 0)
+      return l; /* pass on errors */
+
+    deinterleave (input_interleaved, input, m_frame_size * 2);
+    for (guint ch = 0; ch < m_dhandle.setup.n_channels; ch++)
+      {
+	const int64 output_per_channel = m_frame_size / m_dhandle.setup.n_channels;
+	const int64 input_per_channel = output_per_channel * 2;
+
+	m_resamplers[ch]->process_block (input + ch * input_per_channel, input_per_channel, output + ch * output_per_channel);
+      }
+    interleave (output, &m_pcm_data[0], m_frame_size);
+
+    m_pcm_frame = frame;
+    return 1;
+  }
+};
+
 } // Bse
 
+using namespace Bse;
+
 extern "C" GslDataHandle*
 bse_data_handle_new_upsample2 (GslDataHandle *src_handle,
                                int            precision_bits)
 {
-  return Bse::DataHandleUpsample2::dh_create (src_handle, precision_bits);
+  DataHandleResample2 *cxx_dh = new DataHandleUpsample2 (src_handle, precision_bits);
+  return DataHandleResample2::dh_create (cxx_dh);
 }
+
+extern "C" GslDataHandle*
+bse_data_handle_new_downsample2 (GslDataHandle *src_handle,
+                                 int            precision_bits)
+{
+  DataHandleResample2 *cxx_dh = new DataHandleDownsample2 (src_handle, precision_bits);
+  return DataHandleResample2::dh_create (cxx_dh);
+}

Modified: trunk/bse/gsldatahandle.h
===================================================================
--- trunk/bse/gsldatahandle.h	2006-10-05 14:51:03 UTC (rev 3934)
+++ trunk/bse/gsldatahandle.h	2006-10-05 15:52:43 UTC (rev 3935)
@@ -113,9 +113,10 @@
 						 int64		   loop_last);
 
 /* --- factor 2 resampling datahandles --- */
-GslDataHandle*	  bse_data_handle_new_upsample2	  (GslDataHandle  *src_handle,  // implemented in bsedatahandle-resample.cc
+GslDataHandle*	  bse_data_handle_new_upsample2	  (GslDataHandle  *src_handle,	    // implemented in bsedatahandle-resample.cc
 						   int             precision_bits);
-GslDataHandle*	  bse_data_handle_new_downsample2 (GslDataHandle  *src_handle); // implemented in bsedatahandle-resample.cc
+GslDataHandle*	  bse_data_handle_new_downsample2 (GslDataHandle  *src_handle,
+						   int             precision_bits); // implemented in bsedatahandle-resample.cc
 
 /* --- xinfo handling --- */
 GslDataHandle* gsl_data_handle_new_add_xinfos     (GslDataHandle *src_handle,

Modified: trunk/bse/tests/resamplehandle.cc
===================================================================
--- trunk/bse/tests/resamplehandle.cc	2006-10-05 14:51:03 UTC (rev 3934)
+++ trunk/bse/tests/resamplehandle.cc	2006-10-05 15:52:43 UTC (rev 3935)
@@ -47,13 +47,27 @@
 }
 
 static double
-check (const vector<float>& input, const vector<double>& expected, int n_channels, int precision_bits, double max_db)
+check (const vector<float>  &input,
+       const vector<double> &expected,
+       int                   n_channels,
+       BseResampler2Mode     resampler_mode,
+       int                   precision_bits,
+       double                max_db)
 {
-  g_return_val_if_fail (input.size() * 2 == expected.size(), 0);
   g_return_val_if_fail (input.size() % n_channels == 0, 0);
   
   GslDataHandle *ihandle = gsl_data_handle_new_mem (n_channels, 32, 44100, 440, input.size(), &input[0], NULL);
-  GslDataHandle *rhandle = bse_data_handle_new_upsample2 (ihandle, precision_bits); 
+  GslDataHandle *rhandle;
+  if (resampler_mode == BSE_RESAMPLER2_MODE_UPSAMPLE)
+    {
+      g_return_val_if_fail (input.size() * 2 == expected.size(), 0);
+      rhandle = bse_data_handle_new_upsample2 (ihandle, precision_bits);
+    }
+  else
+    {
+      g_return_val_if_fail (input.size() == expected.size() * 2, 0);
+      rhandle = bse_data_handle_new_downsample2 (ihandle, precision_bits); 
+    }
   gsl_data_handle_unref (ihandle);
 
   BseErrorType error = gsl_data_handle_open (rhandle);
@@ -122,64 +136,101 @@
   return samples_per_second / 44100.0;
 }
 
+template<typename Sample> static void
+generate_test_signal (vector<Sample> &signal,
+		      const size_t    signal_length,
+		      const double    sample_rate,
+                      const double    frequency1,
+		      const double    frequency2 = -1)
+{
+  signal.clear();
+  for (size_t i = 0; i < signal_length; i++)
+    {
+      double wpos = (i * 2 - double (signal_length)) / signal_length;
+
+      double phase1 = i * 2 * M_PI * frequency1 / sample_rate;
+      signal.push_back (sin (phase1) * bse_window_blackman (wpos));
+
+      if (frequency2 > 0)   /* stereo */
+	{
+	  double phase2 = i * 2 * M_PI * frequency2 / sample_rate;
+	  signal.push_back (sin (phase2) * bse_window_blackman (wpos));
+	}
+    }
+}
+
 static void
 run_tests (const char *run_type)
 {
   struct TestParameters {
     int bits;
-    double mono_db;
-    double stereo_db;
+    double mono_upsample_db;
+    double stereo_upsample_db;
+    double mono_downsample_db;
+    double stereo_downsample_db;
   } params[] =
   {
-    { 8, -48, -48 },
-    { 12, -72, -72 },
-    { 16, -98, -95 },
-    { 20, -120, -117 },
-    { 24, -125, -125 }, /* this is not _really_ 24 bit, because the filter is computed using floats */
+    {  8,  -48,  -48, -48,   -48 },
+    { 12,  -72,  -72, -72,   -72 },
+    { 16,  -98,  -95, -96,   -96 },
+    { 20, -120, -117, -120, -120 },
+    { 24, -125, -125, -137, -135 },
     { 0, 0, 0 }
   };
 
   for (int p = 0; params[p].bits; p++)
     {
-      const int LEN = 44100*10;
+      const int LEN = 44100 * 4;
       vector<float> input;
       vector<double> expected;
-      for (int i = 0; i < LEN; i++)
-	{
-	  input.push_back (sin (i * 2 * M_PI * 440.0 / 44100.0) * bse_window_blackman (double (i * 2 - LEN) / LEN));
 
-	  double j = i + 0.5; /* compute perfectly interpolated result */
-	  expected.push_back (sin (i * 2 * M_PI * 440.0 / 44100.0) * bse_window_blackman (double (i * 2 - LEN) / LEN));
-	  expected.push_back (sin (j * 2 * M_PI * 440.0 / 44100.0) * bse_window_blackman (double (j * 2 - LEN) / LEN));
-	}
+      // mono upsampling test
+      {
+	generate_test_signal (input, LEN, 44100, 440);
+	generate_test_signal (expected, LEN * 2, 88200, 440);
 
-      // mono test
+	TSTART ("ResampleHandle %dbits mono upsampling (%s)", params[p].bits, run_type);
+	double streams = check (input, expected, 1, BSE_RESAMPLER2_MODE_UPSAMPLE,
+	                        params[p].bits, params[p].mono_upsample_db);
+	TDONE();
+
+	g_printerr ("    ===> speed is equivalent to %.2f simultaneous 44100 Hz streams\n", streams);
+      }
+
+      // stereo upsampling test
       {
-	TSTART ("ResampleHandle %dbits mono (%s)", params[p].bits, run_type);
-	double streams = check (input, expected, 1, params[p].bits, params[p].mono_db);
+	generate_test_signal (input, LEN, 44100, 440, 1000);
+	generate_test_signal (expected, LEN * 2, 88200, 440, 1000);
+
+        TSTART ("ResampleHandle %dbits stereo upsampling (%s)", params[p].bits, run_type);
+	double streams = check (input, expected, 2, BSE_RESAMPLER2_MODE_UPSAMPLE,
+	                        params[p].bits, params[p].stereo_upsample_db);
 	TDONE();
 
 	g_printerr ("    ===> speed is equivalent to %.2f simultaneous 44100 Hz streams\n", streams);
       }
 
-      input.clear();
-      expected.clear();
-      for (int i = 0; i < LEN; i++)
-	{
-	  input.push_back (sin (i * 2 * M_PI * 440.0 / 44100.0) * bse_window_blackman (double (i * 2 - LEN) / LEN));
-	  input.push_back (sin (i * 2 * M_PI * 1000.0 / 44100.0) * bse_window_blackman (double (i * 2 - LEN) / LEN));
+      // mono downsampling test
+      {
+	generate_test_signal (input, LEN, 44100, 440);
+	generate_test_signal (expected, LEN / 2, 22050, 440);
 
-	  double j = i + 0.5; /* compute perfectly interpolated result */
-	  expected.push_back (sin (i * 2 * M_PI * 440.0 / 44100.0) * bse_window_blackman (double (i * 2 - LEN) / LEN));
-	  expected.push_back (sin (i * 2 * M_PI * 1000.0 / 44100.0) * bse_window_blackman (double (i * 2 - LEN) / LEN));
-	  expected.push_back (sin (j * 2 * M_PI * 440.0 / 44100.0) * bse_window_blackman (double (j * 2 - LEN) / LEN));
-	  expected.push_back (sin (j * 2 * M_PI * 1000.0 / 44100.0) * bse_window_blackman (double (j * 2 - LEN) / LEN));
-	}
+	TSTART ("ResampleHandle %dbits mono downsampling (%s)", params[p].bits, run_type);
+	double streams = check (input, expected, 1, BSE_RESAMPLER2_MODE_DOWNSAMPLE,
+	                        params[p].bits, params[p].mono_downsample_db);
+	TDONE();
 
-      // stereo test
+	g_printerr ("    ===> speed is equivalent to %.2f simultaneous 44100 Hz streams\n", streams);
+      }
+
+      // stereo downsampling test
       {
-        TSTART ("ResampleHandle %dbits stereo (%s)", params[p].bits, run_type);
-	double streams = check (input, expected, 2, params[p].bits, params[p].stereo_db);
+	generate_test_signal (input, LEN, 44100, 440, 1000);
+	generate_test_signal (expected, LEN / 2, 22050, 440, 1000);
+
+        TSTART ("ResampleHandle %dbits stereo downsampling (%s)", params[p].bits, run_type);
+	double streams = check (input, expected, 2, BSE_RESAMPLER2_MODE_DOWNSAMPLE,
+	                        params[p].bits, params[p].stereo_downsample_db);
 	TDONE();
 
 	g_printerr ("    ===> speed is equivalent to %.2f simultaneous 44100 Hz streams\n", streams);




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