shithub: libsamplerate

Download patch

ref: 945b9939d296c939385fbecfc762c4c335f73dfe
parent: b2f7a32263e5335787e0110213619e68cdfdf960
author: Peter Hoyes <pahoyes@gmail.com>
date: Wed Oct 4 07:26:24 EDT 2017

Add ability to clone a SRC_STATE* handle

Signed-off-by: Erik de Castro Lopo <erikd@mega-nerd.com>

--- a/src/common.h
+++ b/src/common.h
@@ -110,6 +110,9 @@
 	/* State reset. */
 	void	(*reset) (struct SRC_PRIVATE_tag *psrc) ;
 
+	/* State clone. */
+	int		(*copy) (struct SRC_PRIVATE_tag *from, struct SRC_PRIVATE_tag *to) ;
+
 	/* Data specific to SRC_MODE_CALLBACK. */
 	src_callback_t	callback_func ;
 	void			*user_callback_data ;
--- a/src/samplerate.c
+++ b/src/samplerate.c
@@ -54,6 +54,34 @@
 } /* src_new */
 
 SRC_STATE*
+src_clone (SRC_STATE* orig, int *error)
+{
+	SRC_PRIVATE	*psrc ;
+	int copy_error ;
+
+	if (error)
+		*error = SRC_ERR_NO_ERROR ;
+
+	if ((psrc = calloc (1, sizeof (*psrc))) == NULL)
+	{	if (error)
+			*error = SRC_ERR_MALLOC_FAILED ;
+		return NULL ;
+		} ;
+
+	SRC_PRIVATE *orig_priv = (SRC_PRIVATE*) orig ;
+	memcpy (psrc, orig_priv, sizeof (SRC_PRIVATE)) ;
+
+	if ((copy_error = orig_priv->copy (orig_priv, psrc)) != SRC_ERR_NO_ERROR)
+	{	if (error)
+			*error = copy_error ;
+		free (psrc) ;
+		psrc = NULL ;
+		} ;
+
+	return (SRC_STATE*) psrc ;
+}
+
+SRC_STATE*
 src_callback_new (src_callback_t func, int converter_type, int channels, int *error, void* cb_data)
 {	SRC_STATE	*src_state ;
 
@@ -245,7 +273,7 @@
 
 	if (error != 0)
 	{	psrc->error = error ;
-	 	return 0 ;
+		return 0 ;
 		} ;
 
 	return output_frames_gen ;
--- a/src/samplerate.h
+++ b/src/samplerate.h
@@ -25,7 +25,7 @@
 /* SRC_DATA is used to pass data to src_simple() and src_process(). */
 typedef struct
 {	const float	*data_in ;
-	float	 *data_out ;
+	float	*data_out ;
 
 	long	input_frames, output_frames ;
 	long	input_frames_used, output_frames_gen ;
@@ -53,6 +53,12 @@
 */
 
 SRC_STATE* src_new (int converter_type, int channels, int *error) ;
+
+/*
+** Clone a handle : return an anonymous pointer to a new converter
+** containing the same internal state as orig. Error returned in *error.
+*/
+SRC_STATE* src_clone (SRC_STATE* orig, int *error) ;
 
 /*
 **	Initilisation for callback based API : return an anonymous pointer to the
--- a/src/src_linear.c
+++ b/src/src_linear.c
@@ -16,6 +16,7 @@
 
 static int linear_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
 static void linear_reset (SRC_PRIVATE *psrc) ;
+static int linear_copy (SRC_PRIVATE *from, SRC_PRIVATE *to) ;
 
 /*========================================================================================
 */
@@ -183,6 +184,7 @@
 	psrc->const_process = linear_vari_process ;
 	psrc->vari_process = linear_vari_process ;
 	psrc->reset = linear_reset ;
+	psrc->copy = linear_copy ;
 
 	linear_reset (psrc) ;
 
@@ -207,3 +209,21 @@
 	return ;
 } /* linear_reset */
 
+static int
+linear_copy (SRC_PRIVATE *from, SRC_PRIVATE *to)
+{
+	if (from->private_data == NULL)
+		return SRC_ERR_NO_PRIVATE ;
+
+	LINEAR_DATA *to_priv = NULL ;
+	LINEAR_DATA* from_priv = (LINEAR_DATA*) from->private_data ;
+	size_t private_size = sizeof (*to_priv) + from_priv->channels * sizeof (float) ;
+
+	if ((to_priv = calloc (1, private_size)) == NULL)
+		return SRC_ERR_MALLOC_FAILED ;
+
+	memcpy (to_priv, from_priv, private_size) ;
+	to->private_data = to_priv ;
+
+	return SRC_ERR_NO_ERROR ;
+} /* linear_copy */
--- a/src/src_sinc.c
+++ b/src/src_sinc.c
@@ -66,6 +66,7 @@
 static int prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) WARN_UNUSED ;
 
 static void sinc_reset (SRC_PRIVATE *psrc) ;
+static int sinc_copy (SRC_PRIVATE *from, SRC_PRIVATE *to) ;
 
 static inline increment_t
 double_to_fp (double x)
@@ -181,6 +182,7 @@
 		psrc->vari_process = sinc_multichan_vari_process ;
 		} ;
 	psrc->reset = sinc_reset ;
+	psrc->copy = sinc_copy ;
 
 	switch (src_enum)
 	{	case SRC_SINC_FASTEST :
@@ -252,6 +254,25 @@
 	/* Set this for a sanity check */
 	memset (filter->buffer + filter->b_len, 0xAA, filter->channels * sizeof (filter->buffer [0])) ;
 } /* sinc_reset */
+
+static int
+sinc_copy (SRC_PRIVATE *from, SRC_PRIVATE *to)
+{
+	if (from->private_data == NULL)
+		return SRC_ERR_NO_PRIVATE ;
+
+	SINC_FILTER *to_filter = NULL ;
+	SINC_FILTER* from_filter = (SINC_FILTER*) from->private_data ;
+	size_t private_length = sizeof (SINC_FILTER) + sizeof (from_filter->buffer [0]) * (from_filter->b_len + from_filter->channels) ;
+
+	if ((to_filter = calloc (1, private_length)) == NULL)
+		return SRC_ERR_MALLOC_FAILED ;
+
+	memcpy (to_filter, from_filter, private_length) ;
+	to->private_data = to_filter ;
+
+	return SRC_ERR_NO_ERROR ;
+} /* sinc_copy */
 
 /*========================================================================================
 **	Beware all ye who dare pass this point. There be dragons here.
--- a/src/src_zoh.c
+++ b/src/src_zoh.c
@@ -16,6 +16,7 @@
 
 static int zoh_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
 static void zoh_reset (SRC_PRIVATE *psrc) ;
+static int zoh_copy (SRC_PRIVATE *from, SRC_PRIVATE *to) ;
 
 /*========================================================================================
 */
@@ -174,6 +175,7 @@
 	psrc->const_process = zoh_vari_process ;
 	psrc->vari_process = zoh_vari_process ;
 	psrc->reset = zoh_reset ;
+	psrc->copy = zoh_copy ;
 
 	zoh_reset (psrc) ;
 
@@ -198,3 +200,21 @@
 	return ;
 } /* zoh_reset */
 
+static int
+zoh_copy (SRC_PRIVATE *from, SRC_PRIVATE *to)
+{
+	if (from->private_data == NULL)
+		return SRC_ERR_NO_PRIVATE ;
+
+	ZOH_DATA *to_priv = NULL ;
+	ZOH_DATA* from_priv = (ZOH_DATA*) from->private_data ;
+	size_t private_size = sizeof (*to_priv) + from_priv->channels * sizeof (float) ;
+
+	if ((to_priv = calloc (1, private_size)) == NULL)
+		return SRC_ERR_MALLOC_FAILED ;
+
+	memcpy (to_priv, from_priv, private_size) ;
+	to->private_data = to_priv ;
+
+	return SRC_ERR_NO_ERROR ;
+} /* zoh_copy */