From 945b9939d296c939385fbecfc762c4c335f73dfe Mon Sep 17 00:00:00 2001 From: Peter Hoyes Date: Wed, 4 Oct 2017 11:26:24 +0100 Subject: [PATCH] Add ability to clone a SRC_STATE* handle Signed-off-by: Erik de Castro Lopo --- src/common.h | 3 +++ src/samplerate.c | 30 +++++++++++++++++++++++++++++- src/samplerate.h | 8 +++++++- src/src_linear.c | 20 ++++++++++++++++++++ src/src_sinc.c | 21 +++++++++++++++++++++ src/src_zoh.c | 20 ++++++++++++++++++++ 6 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/common.h b/src/common.h index 10b35366..db9d595f 100644 --- a/src/common.h +++ b/src/common.h @@ -110,6 +110,9 @@ typedef struct SRC_PRIVATE_tag /* 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 ; diff --git a/src/samplerate.c b/src/samplerate.c index 313f1092..a58f84cf 100644 --- a/src/samplerate.c +++ b/src/samplerate.c @@ -53,6 +53,34 @@ src_new (int converter_type, int channels, int *error) return (SRC_STATE*) psrc ; } /* 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 @@ src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data) if (error != 0) { psrc->error = error ; - return 0 ; + return 0 ; } ; return output_frames_gen ; diff --git a/src/samplerate.h b/src/samplerate.h index ac0f2b08..ac25f85a 100644 --- a/src/samplerate.h +++ b/src/samplerate.h @@ -25,7 +25,7 @@ typedef struct SRC_STATE_tag SRC_STATE ; /* 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 ; @@ -54,6 +54,12 @@ typedef long (*src_callback_t) (void *cb_data, float **data) ; 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 ** internal state of the converter. Choose a converter from the enums below. diff --git a/src/src_linear.c b/src/src_linear.c index c239a085..a9a34e70 100644 --- 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 @@ linear_set_converter (SRC_PRIVATE *psrc, int src_enum) 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 @@ linear_reset (SRC_PRIVATE *psrc) 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 */ diff --git a/src/src_sinc.c b/src/src_sinc.c index b0e6b3df..0e4c31f1 100644 --- a/src/src_sinc.c +++ b/src/src_sinc.c @@ -66,6 +66,7 @@ static int sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ; 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 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum) psrc->vari_process = sinc_multichan_vari_process ; } ; psrc->reset = sinc_reset ; + psrc->copy = sinc_copy ; switch (src_enum) { case SRC_SINC_FASTEST : @@ -253,6 +255,25 @@ sinc_reset (SRC_PRIVATE *psrc) 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. */ diff --git a/src/src_zoh.c b/src/src_zoh.c index 93ffc236..ea251bee 100644 --- 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 @@ zoh_set_converter (SRC_PRIVATE *psrc, int src_enum) 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 @@ zoh_reset (SRC_PRIVATE *psrc) 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 */