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 */