r4109 - in trunk/bse: . tests



Author: stw
Date: 2006-11-27 14:31:25 -0500 (Mon, 27 Nov 2006)
New Revision: 4109

Modified:
   trunk/bse/ChangeLog
   trunk/bse/bsedatahandle-resample.cc
   trunk/bse/gsldatahandle-mad.c
   trunk/bse/gsldatahandle-vorbis.c
   trunk/bse/gsldatahandle.c
   trunk/bse/gsldatahandle.h
   trunk/bse/tests/loophandle.c
   trunk/bse/tests/resamplehandle.cc
Log:
Mon Nov 27 20:29:53 2006  Stefan Westerfeld  <stefan space twc de>

	* gsldatahandle.[hc]: Added new gsl_data_handle_get_state_length
	function for datahandles, with a corresponding vtable entry. For
	filtering datahandles (such as lowpass handles), which are usually
	stateful, it returns the filter state length.

	* gsldatahandle-vorbis.c:
	* gsldatahandle-mad.c:
	* bsedatahandle-resample.cc:
	* tests/loophandle.c: Implement the get_state_length datahandle
	method.

	* tests/resamplehandle.cc: Test the resampler get_state_length
	function.


Modified: trunk/bse/ChangeLog
===================================================================
--- trunk/bse/ChangeLog	2006-11-27 14:24:02 UTC (rev 4108)
+++ trunk/bse/ChangeLog	2006-11-27 19:31:25 UTC (rev 4109)
@@ -1,3 +1,19 @@
+Mon Nov 27 20:29:53 2006  Stefan Westerfeld  <stefan space twc de>
+
+	* gsldatahandle.[hc]: Added new gsl_data_handle_get_state_length
+	function for datahandles, with a corresponding vtable entry. For
+	filtering datahandles (such as lowpass handles), which are usually
+	stateful, it returns the filter state length.
+
+	* gsldatahandle-vorbis.c:
+	* gsldatahandle-mad.c:
+	* bsedatahandle-resample.cc:
+	* tests/loophandle.c: Implement the get_state_length datahandle
+	method.
+
+	* tests/resamplehandle.cc: Test the resampler get_state_length
+	function.
+
 Mon Nov 27 15:19:47 2006  Stefan Westerfeld  <stefan space twc de>
 
 	* tests/firhandle.cc: Check that the filter is zero phase in the

Modified: trunk/bse/bsedatahandle-resample.cc
===================================================================
--- trunk/bse/bsedatahandle-resample.cc	2006-11-27 14:24:02 UTC (rev 4108)
+++ trunk/bse/bsedatahandle-resample.cc	2006-11-27 19:31:25 UTC (rev 4109)
@@ -137,7 +137,7 @@
   }
 
   /* implemented by upsampling and downsampling datahandle */
-  virtual BseResampler2Mode mode	() = 0;
+  virtual BseResampler2Mode mode	() const = 0;
   virtual int64		    read_frame  (int64 frame) = 0;
 
 public:
@@ -238,7 +238,28 @@
 
     return n_values;
   }
+  int64
+  get_state_length() const
+  {
+    int64 source_state_length = gsl_data_handle_get_state_length (m_src_handle);
+    // m_src_handle must be opened and have valid state size
+    g_return_val_if_fail (source_state_length >= 0, 0);  
 
+    if (mode() == BSE_RESAMPLER2_MODE_UPSAMPLE)
+      source_state_length *= 2;
+    else
+      source_state_length = (source_state_length + 1) / 2;
+
+    // we must be opened => n_channels > 0, 1 Resampler per Channel
+    g_return_val_if_fail (!m_resamplers.empty(), 0);
+
+    /* For fractional delays, a delay of 10.5 for instance means that input[0]
+     * affects samples 10 and 11, and thus the state length we assume for
+     * that case is 11.
+     */
+    int64 per_channel_state = ceil (m_resamplers[0]->delay());
+    return source_state_length + per_channel_state * m_dhandle.setup.n_channels;
+  }
   static GslDataHandle*
   dh_create (DataHandleResample2 *cxx_dh)
   {
@@ -248,8 +269,10 @@
       dh_read,
       dh_close,
       NULL,
+      dh_get_state_length,
       dh_destroy,
     };
+
     if (cxx_dh->m_init_ok)
       {
 	cxx_dh->m_dhandle.vtable = &dh_vtable;
@@ -262,7 +285,6 @@
 	return NULL;
       }
   }
-
 private:
 /* for the "C" API (vtable) */
   static DataHandleResample2*
@@ -294,6 +316,11 @@
   {
     return dh_cast (dhandle)->read (voffset, n_values, values);
   }
+  static int64
+  dh_get_state_length (GslDataHandle *dhandle)
+  {
+    return dh_cast (dhandle)->get_state_length();
+  }
 };
 
 class DataHandleUpsample2 : public DataHandleResample2
@@ -307,7 +334,7 @@
       m_dhandle.name = g_strconcat (m_src_handle->name, "// #upsample2 /", NULL);
   }
   BseResampler2Mode
-  mode()
+  mode() const
   {
     return BSE_RESAMPLER2_MODE_UPSAMPLE;
   }
@@ -382,7 +409,7 @@
   {
   }
   BseResampler2Mode
-  mode()
+  mode() const
   {
     return BSE_RESAMPLER2_MODE_DOWNSAMPLE;
   }

Modified: trunk/bse/gsldatahandle-mad.c
===================================================================
--- trunk/bse/gsldatahandle-mad.c	2006-11-27 14:24:02 UTC (rev 4108)
+++ trunk/bse/gsldatahandle-mad.c	2006-11-27 19:31:25 UTC (rev 4109)
@@ -673,6 +673,7 @@
   dh_mad_read,
   dh_mad_close,
   NULL,
+  NULL,
   dh_mad_destroy,
 };
 

Modified: trunk/bse/gsldatahandle-vorbis.c
===================================================================
--- trunk/bse/gsldatahandle-vorbis.c	2006-11-27 14:24:02 UTC (rev 4108)
+++ trunk/bse/gsldatahandle-vorbis.c	2006-11-27 19:31:25 UTC (rev 4109)
@@ -365,6 +365,7 @@
   dh_vorbis_read,
   dh_vorbis_close,
   NULL,
+  NULL,
   dh_vorbis_destroy,
 };
 

Modified: trunk/bse/gsldatahandle.c
===================================================================
--- trunk/bse/gsldatahandle.c	2006-11-27 14:24:02 UTC (rev 4108)
+++ trunk/bse/gsldatahandle.c	2006-11-27 19:31:25 UTC (rev 4109)
@@ -195,7 +195,42 @@
   return src_handle;
 }
 
+/**
+ * @param data_handle	a DataHandle
+ * @return		the state length of the data handle
+ *
+ * Most data handles produce output samples from an input data handle.
+ * Some of them, like filtering and resampling datahandles, have an internal
+ * state which means that the value of one input sample affects not only one
+ * output sample, but some samples before and/or some samples after the
+ * "corresponding" output sample.
+ *
+ * Often the state is symmetric, so that the number of output samples affected
+ * before and after the "corresponding" output sample is the same. Then the
+ * function returns this number. If the state is asymmetric, this function
+ * shall return the maximum of the two numbers.
+ *
+ * If multiple data handles are nested (for instance when resampling a
+ * filtered signal), the function propagates the state length, so that the
+ * accumulated state length of all operations together is returned.
+ *
+ * Note: This function can only be used while the data handle is opened.
+ *
+ * This function is MT-safe and may be called from any thread.
+ */
 int64
+gsl_data_handle_get_state_length (GslDataHandle *dhandle)
+{
+  g_return_val_if_fail (dhandle != NULL, -1);
+  g_return_val_if_fail (dhandle->open_count > 0, -1);
+
+  GSL_SPIN_LOCK (&dhandle->mutex);
+  int64 state_length = dhandle->vtable->get_state_length ? dhandle->vtable->get_state_length (dhandle) : 0;
+  GSL_SPIN_UNLOCK (&dhandle->mutex);
+  return state_length;
+}
+
+int64
 gsl_data_handle_length (GslDataHandle *dhandle)
 {
   int64 l;
@@ -355,6 +390,7 @@
     mem_handle_read,
     mem_handle_close,
     NULL,
+    NULL,
     mem_handle_destroy,
   };
   MemHandle *mhandle;
@@ -500,6 +536,14 @@
   return chandle->src_handle;
 }
 
+static int64
+xinfo_get_state_length (GslDataHandle *dhandle)
+{
+  XInfoHandle *chandle = (XInfoHandle*) dhandle;
+  return gsl_data_handle_get_state_length (chandle->src_handle);
+}
+
+
 static GslDataHandle*
 xinfo_data_handle_new (GslDataHandle *src_handle,
                        gboolean       clear_xinfos,
@@ -511,6 +555,7 @@
     xinfo_handle_read,
     xinfo_handle_close,
     xinfo_get_source_handle,
+    xinfo_get_state_length,
     xinfo_handle_destroy,
   };
   SfiRing *dest_added = NULL, *dest_remove = NULL;
@@ -686,6 +731,12 @@
   gsl_data_handle_close (chandle->src_handle);
 }
 
+static int64
+chain_handle_get_state_length (GslDataHandle *dhandle)
+{
+  ChainHandle *chandle = (ChainHandle*) dhandle;
+  return gsl_data_handle_get_state_length (chandle->src_handle);
+}
 
 /* --- reversed handle --- */
 static void
@@ -745,6 +796,7 @@
     reverse_handle_read,
     chain_handle_close,
     NULL,
+    chain_handle_get_state_length,
     reverse_handle_destroy,
   };
   ReversedHandle *rhandle;
@@ -853,6 +905,7 @@
     cut_handle_read,
     chain_handle_close,
     NULL,
+    chain_handle_get_state_length,
     cut_handle_destroy,
   };
   CutHandle *chandle;
@@ -1032,6 +1085,14 @@
   return orig_n_values - n_values;
 }
 
+static int64
+insert_handle_get_state_length (GslDataHandle *dhandle)
+{
+  InsertHandle *ihandle = (InsertHandle*) dhandle;
+  return gsl_data_handle_get_state_length (ihandle->src_handle);
+}
+
+
 GslDataHandle*
 gsl_data_handle_new_insert (GslDataHandle *src_handle,
 			    guint          paste_bit_depth,
@@ -1045,6 +1106,7 @@
     insert_handle_read,
     insert_handle_close,
     NULL,
+    insert_handle_get_state_length,
     insert_handle_destroy,
   };
   InsertHandle *ihandle;
@@ -1161,6 +1223,7 @@
     loop_handle_read,
     chain_handle_close,
     NULL,
+    chain_handle_get_state_length,
     loop_handle_destroy,
   };
   LoopHandle *lhandle;
@@ -1259,6 +1322,13 @@
   return chandle->dcache->dhandle;
 }
 
+static int64
+dcache_handle_get_state_length (GslDataHandle *dhandle)
+{
+  DCacheHandle *chandle = (DCacheHandle*) dhandle;
+  return gsl_data_handle_get_state_length (chandle->dcache->dhandle);
+}
+
 GslDataHandle*
 gsl_data_handle_new_dcached (GslDataCache *dcache)
 {
@@ -1267,6 +1337,7 @@
     dcache_handle_read,
     dcache_handle_close,
     dcache_handle_get_source_handle,
+    dcache_handle_get_state_length,
     dcache_handle_destroy,
   };
   DCacheHandle *dhandle;
@@ -1495,6 +1566,7 @@
     wave_handle_read,
     wave_handle_close,
     NULL,
+    NULL,
     wave_handle_destroy,
   };
   WaveHandle *whandle;

Modified: trunk/bse/gsldatahandle.h
===================================================================
--- trunk/bse/gsldatahandle.h	2006-11-27 14:24:02 UTC (rev 4108)
+++ trunk/bse/gsldatahandle.h	2006-11-27 19:31:25 UTC (rev 4109)
@@ -63,60 +63,62 @@
 					 gfloat			*values);
   void		 (*close)		(GslDataHandle		*data_handle);
   GslDataHandle* (*get_source)          (GslDataHandle          *data_handle);
+  int64          (*get_state_length)	(GslDataHandle	        *data_handle);
   void           (*destroy)		(GslDataHandle		*data_handle);
 };
 
 
 
 /* --- standard functions --- */
-GslDataHandle*	  gsl_data_handle_ref		(GslDataHandle	  *dhandle);
-void		  gsl_data_handle_unref		(GslDataHandle	  *dhandle);
-BseErrorType	  gsl_data_handle_open		(GslDataHandle	  *dhandle);
-void		  gsl_data_handle_close		(GslDataHandle	  *dhandle);
-int64		  gsl_data_handle_length	(GslDataHandle	  *data_handle);
-#define	          gsl_data_handle_n_values(      dh) \
-		                                 gsl_data_handle_length (dh)
-guint		  gsl_data_handle_n_channels	(GslDataHandle	  *data_handle);
-guint		  gsl_data_handle_bit_depth	(GslDataHandle	  *data_handle);
-gfloat		  gsl_data_handle_mix_freq	(GslDataHandle	  *data_handle);
-gfloat		  gsl_data_handle_osc_freq	(GslDataHandle	  *data_handle);
-const gchar*	  gsl_data_handle_name		(GslDataHandle	  *data_handle);
-int64		  gsl_data_handle_read		(GslDataHandle	  *data_handle,
-						 int64		   value_offset,
-						 int64		   n_values,
-						 gfloat		  *values);
-GslDataHandle*    gsl_data_handle_get_source    (GslDataHandle    *dhandle);
-GslDataHandle*	  gsl_data_handle_new_cut	(GslDataHandle	  *src_handle,
-						 int64		   cut_offset,
-						 int64		   n_cut_values);
-GslDataHandle*	  gsl_data_handle_new_crop	(GslDataHandle	  *src_handle,
-						 int64  	   n_head_cut,
-						 int64		   n_tail_cut);
-GslDataHandle*	  gsl_data_handle_new_reverse	(GslDataHandle	  *src_handle);
-GslDataHandle*	  gsl_data_handle_new_insert	(GslDataHandle	  *src_handle,
-						 guint             pasted_bit_depth,
-						 int64		   insertion_offset,
-						 int64		   n_paste_values,
-						 const gfloat	  *paste_values,
-						 void            (*free) (gpointer values));
-GslDataHandle*	  gsl_data_handle_new_mem	(guint		   n_channels,
-						 guint             bit_depth,
-                                                 gfloat            mix_freq,
-                                                 gfloat            osc_freq,
-						 int64		   n_values,
-						 const gfloat	  *values,
-						 void            (*free) (gpointer values));
-GslDataHandle*	  gsl_data_handle_new_dcached	(GslDataCache	  *dcache);
+GslDataHandle*	  gsl_data_handle_ref		    (GslDataHandle	  *dhandle);
+void		  gsl_data_handle_unref		    (GslDataHandle	  *dhandle);
+BseErrorType	  gsl_data_handle_open		    (GslDataHandle	  *dhandle);
+void		  gsl_data_handle_close		    (GslDataHandle	  *dhandle);
+int64		  gsl_data_handle_length	    (GslDataHandle	  *data_handle);
+#define	          gsl_data_handle_n_values(	     dh) \
+						     gsl_data_handle_length (dh)
+guint		  gsl_data_handle_n_channels	    (GslDataHandle	  *data_handle);
+guint		  gsl_data_handle_bit_depth	    (GslDataHandle	  *data_handle);
+gfloat		  gsl_data_handle_mix_freq	    (GslDataHandle	  *data_handle);
+gfloat		  gsl_data_handle_osc_freq	    (GslDataHandle	  *data_handle);
+const gchar*	  gsl_data_handle_name		    (GslDataHandle	  *data_handle);
+int64		  gsl_data_handle_read		    (GslDataHandle	  *data_handle,
+						     int64		   value_offset,
+						     int64		   n_values,
+						     gfloat		  *values);
+int64		  gsl_data_handle_get_state_length  (GslDataHandle    *dhandle);
+GslDataHandle*    gsl_data_handle_get_source	    (GslDataHandle    *dhandle);
+GslDataHandle*	  gsl_data_handle_new_cut	    (GslDataHandle	  *src_handle,
+						     int64		   cut_offset,
+						     int64		   n_cut_values);
+GslDataHandle*	  gsl_data_handle_new_crop	    (GslDataHandle	  *src_handle,
+						     int64  	   n_head_cut,
+						     int64		   n_tail_cut);
+GslDataHandle*	  gsl_data_handle_new_reverse	    (GslDataHandle	  *src_handle);
+GslDataHandle*	  gsl_data_handle_new_insert	    (GslDataHandle	  *src_handle,
+						     guint             pasted_bit_depth,
+						     int64		   insertion_offset,
+						     int64		   n_paste_values,
+						     const gfloat	  *paste_values,
+						     void            (*free) (gpointer values));
+GslDataHandle*	  gsl_data_handle_new_mem	    (guint		   n_channels,
+						     guint             bit_depth,
+						     gfloat            mix_freq,
+						     gfloat            osc_freq,
+						     int64		   n_values,
+						     const gfloat	  *values,
+						     void            (*free) (gpointer values));
+GslDataHandle*	  gsl_data_handle_new_dcached	    (GslDataCache	  *dcache);
 /* cheap and inefficient, testpurpose only */
-GslDataHandle*	  gsl_data_handle_new_looped	(GslDataHandle	  *src_handle,
-						 int64		   loop_first,
-						 int64		   loop_last);
+GslDataHandle*	  gsl_data_handle_new_looped	    (GslDataHandle	  *src_handle,
+						     int64		   loop_first,
+						     int64		   loop_last);
 
 /* --- factor 2 resampling datahandles --- */
-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,
-						   int             precision_bits); // 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,
+						     int             precision_bits);	// implemented in bsedatahandle-resample.cc
 
 GslDataHandle* gsl_data_handle_new_fir_highpass   (GslDataHandle *src_handle, // implemented in bsedatahandle-fir.cc
 				                   gdouble        cutoff_freq,
@@ -124,11 +126,11 @@
 
 
 /* --- xinfo handling --- */
-GslDataHandle* gsl_data_handle_new_add_xinfos     (GslDataHandle *src_handle,
-                                                   gchar        **xinfos);
-GslDataHandle* gsl_data_handle_new_remove_xinfos  (GslDataHandle *src_handle,
-                                                   gchar        **xinfos);
-GslDataHandle* gsl_data_handle_new_clear_xinfos   (GslDataHandle *src_handle);
+GslDataHandle* gsl_data_handle_new_add_xinfos	    (GslDataHandle *src_handle,
+						     gchar        **xinfos);
+GslDataHandle* gsl_data_handle_new_remove_xinfos    (GslDataHandle *src_handle,
+						     gchar        **xinfos);
+GslDataHandle* gsl_data_handle_new_clear_xinfos	    (GslDataHandle *src_handle);
 
 
 /* --- wave specific functions --- */

Modified: trunk/bse/tests/loophandle.c
===================================================================
--- trunk/bse/tests/loophandle.c	2006-11-27 14:24:02 UTC (rev 4108)
+++ trunk/bse/tests/loophandle.c	2006-11-27 19:31:25 UTC (rev 4109)
@@ -82,9 +82,9 @@
 
 static GslLong
 loop_handle_reference_read (GslDataHandle *dhandle,
-		  GslLong        voffset,
-		  GslLong        n_values,
-		  gfloat        *values)
+			    GslLong        voffset,
+			    GslLong        n_values,
+			    gfloat        *values)
 {
   LoopHandleReference *lhandle = (LoopHandleReference*) dhandle;
   
@@ -105,6 +105,14 @@
     }
 }
 
+static int64
+loop_handle_reference_get_state_length (GslDataHandle *dhandle)
+{
+  LoopHandleReference *lhandle = (LoopHandleReference*) dhandle;
+  return gsl_data_handle_get_state_length (lhandle->src_handle);
+}
+
+
 static GslDataHandle*
 gsl_data_handle_new_looped_reference (GslDataHandle *src_handle,
 			              GslLong        loop_first,
@@ -115,6 +123,7 @@
     loop_handle_reference_read,
     loop_handle_reference_close,
     NULL,
+    loop_handle_reference_get_state_length,
     loop_handle_reference_destroy,
   };
   LoopHandleReference *lhandle;

Modified: trunk/bse/tests/resamplehandle.cc
===================================================================
--- trunk/bse/tests/resamplehandle.cc	2006-11-27 14:24:02 UTC (rev 4108)
+++ trunk/bse/tests/resamplehandle.cc	2006-11-27 19:31:25 UTC (rev 4109)
@@ -371,6 +371,111 @@
   TDONE();
 }
 
+static void
+test_state_length (const char *run_type)
+{
+  TSTART ("Resampler State Length Info (%s)", run_type);
+
+  //-----------------------------------------------------------------------------------
+  // usampling
+  //-----------------------------------------------------------------------------------
+  {
+    const guint period_size = 107;
+
+    /* fill input with 2 periods of a sine wave, so that while at the start and
+     * at the end clicks occur (because the unwindowed signal is assumed to 0 by
+     * the resamplehandle), in the middle 1 period can be found that is clickless
+     */
+    vector<float> input (period_size * 2);
+    for (size_t i = 0; i < input.size(); i++)
+      input[i] = sin (i * 2 * M_PI / period_size);
+
+    const guint precision_bits = 16;
+    GslDataHandle *ihandle = gsl_data_handle_new_mem (1, 32, 44100, 440, input.size(), &input[0], NULL);
+    GslDataHandle *rhandle = bse_data_handle_new_upsample2 (ihandle, precision_bits);
+    BseErrorType open_error = gsl_data_handle_open (rhandle);
+    TASSERT (open_error == 0);
+    TASSERT (gsl_data_handle_get_state_length (ihandle) == 0);
+
+    // determine how much of the end of the signal is "unusable" due to the resampler state:
+    const int64 state_length = gsl_data_handle_get_state_length (rhandle);
+
+    /* read resampled signal in the range unaffected by the resampler state (that
+     * is: not at the directly at the beginning, and not directly at the end)
+     */
+    vector<float> output (input.size() * 3);
+    for (size_t values_done = 0; values_done < output.size(); values_done++)
+      {
+	/* NOTE: this is an inlined implementation of a loop, which you normally would
+	 * implement with a loop handle, and it is inefficient because we read the
+	 * samples one-by-one -> usually: don't use such code, always read in blocks */
+	int64 read_pos = (values_done + state_length) % (period_size * 2) + (period_size * 2 - state_length);
+	TCHECK (read_pos >= state_length);   /* check that input signal was long enough to be for this test */
+	int64 values_read = gsl_data_handle_read (rhandle, read_pos, 1, &output[values_done]);
+	TCHECK (values_read == 1);
+      }
+    double error = 0;
+    for (size_t i = 0; i < output.size(); i++)
+      {
+	double expected = sin (i * 2 * M_PI / (period_size * 2));
+	error = MAX (error, fabs (output[i] - expected));
+      }
+    double error_db = bse_db_from_factor (error, -200);
+    TASSERT (error_db < -97);
+  }
+
+  //-----------------------------------------------------------------------------------
+  // downsampling
+  //-----------------------------------------------------------------------------------
+
+  {
+    const guint period_size = 190;
+
+    /* fill input with 2 periods of a sine wave, so that while at the start and
+     * at the end clicks occur (because the unwindowed signal is assumed to 0 by
+     * the resamplehandle), in the middle 1 period can be found that is clickless
+     */
+    vector<float> input (period_size * 2);
+    for (size_t i = 0; i < input.size(); i++)
+      input[i] = sin (i * 2 * M_PI / period_size);
+
+    const guint precision_bits = 16;
+    GslDataHandle *ihandle = gsl_data_handle_new_mem (1, 32, 44100, 440, input.size(), &input[0], NULL);
+    GslDataHandle *rhandle = bse_data_handle_new_downsample2 (ihandle, precision_bits);
+    BseErrorType open_error = gsl_data_handle_open (rhandle);
+    TASSERT (open_error == 0);
+    TASSERT (gsl_data_handle_get_state_length (ihandle) == 0);
+
+    // determine how much of the end of the signal is "unusable" due to the resampler state:
+    const int64 state_length = gsl_data_handle_get_state_length (rhandle);
+
+    /* read resampled signal in the range unaffected by the resampler state (that
+     * is: not at the directly at the beginning, and not directly at the end)
+     */
+    vector<float> output (input.size() * 3 / 2);
+    for (size_t values_done = 0; values_done < output.size(); values_done++)
+      {
+	/* NOTE: this is an inlined implementation of a loop, which you normally would
+	 * implement with a loop handle, and it is inefficient because we read the
+	 * samples one-by-one -> usually: don't use such code, always read in blocks */
+	int64 read_pos = (values_done + state_length) % (period_size / 2) + (period_size / 2 - state_length);
+	TCHECK (read_pos >= state_length);   /* check that input signal was long enough to be for this test */
+	int64 values_read = gsl_data_handle_read (rhandle, read_pos, 1, &output[values_done]);
+	TCHECK (values_read == 1);
+      }
+    double error = 0;
+    for (size_t i = 0; i < output.size(); i++)
+      {
+	double expected = sin (i * 2 * M_PI / (period_size / 2));
+	error = MAX (error, fabs (output[i] - expected));
+      }
+    double error_db = bse_db_from_factor (error, -200);
+    TASSERT (error_db < -105);
+  }
+  TDONE();
+}
+
+
 int
 main (int   argc,
       char *argv[])
@@ -385,6 +490,7 @@
   
   test_c_api ("FPU");
   test_delay_compensation ("FPU");
+  test_state_length ("FPU");
   run_tests ("FPU");
 
   /* load plugins */
@@ -399,6 +505,7 @@
 
   test_c_api ("SSE");
   test_delay_compensation ("SSE");
+  test_state_length ("SSE");
   run_tests ("SSE");
 
   return 0;




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