shithub: libsamplerate

Download patch

ref: 26d92c369394bcd0b0cea488890edce1a0d757d5
parent: c28af3dece9b149341ec8020259fc46b9a314740
author: evpobr <evpobr@gmail.com>
date: Wed Nov 11 07:32:24 EST 2020

Refactor convertors initialization

--- a/src/common.h
+++ b/src/common.h
@@ -134,19 +134,19 @@
 const char* sinc_get_name (int src_enum) ;
 const char* sinc_get_description (int src_enum) ;
 
-SRC_ERROR sinc_set_converter (SRC_STATE *state, int src_enum) ;
+SRC_STATE *sinc_state_new (int converter_type, int channels, SRC_ERROR *error) ;
 
 /* In src_linear.c */
 const char* linear_get_name (int src_enum) ;
 const char* linear_get_description (int src_enum) ;
 
-SRC_ERROR linear_set_converter (SRC_STATE *state, int src_enum) ;
+SRC_STATE *linear_state_new (int channels, SRC_ERROR *error) ;
 
 /* In src_zoh.c */
 const char* zoh_get_name (int src_enum) ;
 const char* zoh_get_description (int src_enum) ;
 
-SRC_ERROR zoh_set_converter (SRC_STATE *state, int src_enum) ;
+SRC_STATE *zoh_state_new (int channels, SRC_ERROR *error) ;
 
 /*----------------------------------------------------------
 **	Common static inline functions.
--- a/src/samplerate.c
+++ b/src/samplerate.c
@@ -16,41 +16,13 @@
 #include	"samplerate.h"
 #include	"common.h"
 
-static int psrc_set_converter (SRC_STATE *state, int converter_type) ;
+static SRC_STATE *psrc_set_converter (int converter_type, int channels, int *error) ;
 
 
 SRC_STATE *
 src_new (int converter_type, int channels, int *error)
 {
-	if (error)
-		*error = SRC_ERR_NO_ERROR ;
-
-	if (channels < 1)
-	{	if (error)
-			*error = SRC_ERR_BAD_CHANNEL_COUNT ;
-		return NULL ;
-		} ;
-
-	SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;
-	if (state == NULL)
-	{	if (error)
-			*error = SRC_ERR_MALLOC_FAILED ;
-		return NULL ;
-		} ;
-
-	state->channels = channels ;
-	state->mode = SRC_MODE_PROCESS ;
-
-	if (psrc_set_converter (state, converter_type) != SRC_ERR_NO_ERROR)
-	{	if (error)
-			*error = SRC_ERR_BAD_CONVERTER ;
-		free (state) ;
-		state = NULL ;
-		} ;
-
-	src_reset (state) ;
-
-	return state ;
+	return psrc_set_converter (converter_type, channels, error) ;
 } /* src_new */
 
 SRC_STATE*
@@ -533,18 +505,33 @@
 **	Private functions.
 */
 
-static int
-psrc_set_converter (SRC_STATE	*state, int converter_type)
+static SRC_STATE *
+psrc_set_converter (int converter_type, int channels, int *error)
 {
-	if (sinc_set_converter (state, converter_type) == SRC_ERR_NO_ERROR)
-		return SRC_ERR_NO_ERROR ;
+	SRC_ERROR temp_error;
+	SRC_STATE *state ;
+	switch (converter_type)
+	{
+	case SRC_SINC_BEST_QUALITY :
+	case SRC_SINC_MEDIUM_QUALITY :
+	case SRC_SINC_FASTEST :
+		state = sinc_state_new (converter_type, channels, &temp_error) ;
+		break ;
+	case SRC_ZERO_ORDER_HOLD :
+		state = zoh_state_new (channels, &temp_error) ;
+		break ;
+	case SRC_LINEAR :
+		state = linear_state_new (channels, &temp_error) ;
+		break ;
+	default :
+		temp_error = SRC_ERR_BAD_CONVERTER ;
+		state = NULL ;
+		break ;
+	}
 
-	if (zoh_set_converter (state, converter_type) == SRC_ERR_NO_ERROR)
-		return SRC_ERR_NO_ERROR ;
+	if (error)
+		*error = (int) temp_error ;
 
-	if (linear_set_converter (state, converter_type) == SRC_ERR_NO_ERROR)
-		return SRC_ERR_NO_ERROR ;
-
-	return SRC_ERR_BAD_CONVERTER ;
+	return state ;
 } /* psrc_set_converter */
 
--- a/src/src_linear.c
+++ b/src/src_linear.c
@@ -6,6 +6,7 @@
 ** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 */
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -158,37 +159,50 @@
 	return NULL ;
 } /* linear_get_descrition */
 
-SRC_ERROR
-linear_set_converter (SRC_STATE *state, int src_enum)
+static LINEAR_DATA *
+linear_data_new (int channels)
 {
-	LINEAR_DATA *priv = NULL ;
+	assert (channels > 0) ;
 
-	if (src_enum != SRC_LINEAR)
-		return SRC_ERR_BAD_CONVERTER ;
-
-	linear_close (state) ;
-
-	if (state->private_data == NULL)
+	LINEAR_DATA *priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ;
+	if (priv)
 	{
-		priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ;
-		if (priv)
+		priv->linear_magic_marker = LINEAR_MAGIC_MARKER ;
+		priv->last_value = (float *) calloc (channels, sizeof (float)) ;
+		if (!priv->last_value)
 		{
-			priv->last_value = (float *) calloc (state->channels, sizeof (float)) ;
-			if (!priv->last_value)
-			{
-				free (priv) ;
-				priv = NULL ;
-			}
+			free (priv) ;
+			priv = NULL ;
 		}
 	}
 
-	if (priv == NULL)
-		return SRC_ERR_MALLOC_FAILED ;
+	return priv ;
+}
 
-	state->private_data = priv ;
+SRC_STATE *
+linear_state_new (int channels, SRC_ERROR *error)
+{
+	assert (channels > 0) ;
+	assert (error != NULL) ;
 
-	priv->linear_magic_marker = LINEAR_MAGIC_MARKER ;
+	SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;
+	if (!state)
+	{
+		*error = SRC_ERR_MALLOC_FAILED ;
+		return NULL ;
+	}
 
+	state->channels = channels ;
+	state->mode = SRC_MODE_PROCESS ;
+
+	state->private_data = linear_data_new (state->channels) ;
+	if (!state->private_data)
+	{
+		free (state) ;
+		*error = SRC_ERR_MALLOC_FAILED ;
+		return NULL ;
+	}
+
 	state->const_process = linear_vari_process ;
 	state->vari_process = linear_vari_process ;
 	state->reset = linear_reset ;
@@ -197,8 +211,10 @@
 
 	linear_reset (state) ;
 
-	return SRC_ERR_NO_ERROR ;
-} /* linear_set_converter */
+	*error = SRC_ERR_NO_ERROR ;
+
+	return state ;
+}
 
 /*===================================================================================
 */
--- a/src/src_sinc.c
+++ b/src/src_sinc.c
@@ -25,6 +25,7 @@
 #define	SHIFT_BITS				12
 #define	FP_ONE					((double) (((increment_t) 1) << SHIFT_BITS))
 #define	INV_FP_ONE				(1.0 / FP_ONE)
+#define MAX_CHANNELS			128
 
 /*========================================================================================
 */
@@ -51,7 +52,7 @@
 	int		b_current, b_end, b_real_end, b_len ;
 
 	/* Sure hope noone does more than 128 channels at once. */
-	double left_calc [128], right_calc [128] ;
+	double left_calc [MAX_CHANNELS], right_calc [MAX_CHANNELS] ;
 
 	float	*buffer ;
 } SINC_FILTER ;
@@ -141,109 +142,131 @@
 	return NULL ;
 } /* sinc_get_descrition */
 
-SRC_ERROR
-sinc_set_converter (SRC_STATE *state, int src_enum)
-{	SINC_FILTER *filter, temp_filter ;
-	increment_t count ;
-	uint32_t bits ;
+static SINC_FILTER *
+sinc_filter_new (int converter_type, int channels)
+{
+	assert (converter_type == SRC_SINC_FASTEST ||
+		converter_type == SRC_SINC_MEDIUM_QUALITY ||
+		converter_type == SRC_SINC_BEST_QUALITY) ;
+	assert (channels > 0 && channels <= MAX_CHANNELS) ;
 
+	SINC_FILTER *priv = (SINC_FILTER *) calloc (1, sizeof (SINC_FILTER)) ;
+	if (priv)
+	{
+		priv->sinc_magic_marker = SINC_MAGIC_MARKER ;
+		switch (converter_type)
+		{
+		case SRC_SINC_FASTEST :
+			priv->coeffs = fastest_coeffs.coeffs ;
+			priv->coeff_half_len = ARRAY_LEN (fastest_coeffs.coeffs) - 2 ;
+			priv->index_inc = fastest_coeffs.increment ;
+			break ;
+
+		case SRC_SINC_MEDIUM_QUALITY :
+			priv->coeffs = slow_mid_qual_coeffs.coeffs ;
+			priv->coeff_half_len = ARRAY_LEN (slow_mid_qual_coeffs.coeffs) - 2 ;
+			priv->index_inc = slow_mid_qual_coeffs.increment ;
+			break ;
+
+		case SRC_SINC_BEST_QUALITY :
+			priv->coeffs = slow_high_qual_coeffs.coeffs ;
+			priv->coeff_half_len = ARRAY_LEN (slow_high_qual_coeffs.coeffs) - 2 ;
+			priv->index_inc = slow_high_qual_coeffs.increment ;
+			break ;
+		}
+
+		priv->b_len = 3 * (int) lrint ((priv->coeff_half_len + 2.0) / priv->index_inc * SRC_MAX_RATIO + 1) ;
+		priv->b_len = MAX (priv->b_len, 4096) ;
+		priv->b_len *= channels ;
+		priv->b_len += 1 ; // There is a <= check against samples_in_hand requiring a buffer bigger than the calculation above
+
+
+		priv->buffer = (float *) calloc (priv->b_len + channels, sizeof (float)) ;
+		if (!priv->buffer)
+		{
+			free (priv) ;
+			priv = NULL ;
+		}
+	}
+
+	return priv ;
+}
+
+SRC_STATE *
+sinc_state_new (int converter_type, int channels, SRC_ERROR *error)
+{
+	assert (converter_type == SRC_SINC_FASTEST ||
+		converter_type == SRC_SINC_MEDIUM_QUALITY ||
+		converter_type == SRC_SINC_BEST_QUALITY) ;
+	assert (channels > 0) ;
+	assert (error != NULL) ;
+
 	/* Quick sanity check. */
 	if (SHIFT_BITS >= sizeof (increment_t) * 8 - 1)
-		return SRC_ERR_SHIFT_BITS ;
+	{
+		*error = SRC_ERR_SHIFT_BITS ;
+		return NULL ;
+	}
 
-	sinc_close (state) ;
+	if (channels > MAX_CHANNELS)
+	{
+		*error = SRC_ERR_BAD_CHANNEL_COUNT ;
+		return NULL ;
+	}
 
-	memset (&temp_filter, 0, sizeof (temp_filter)) ;
+	SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;
+	if (!state)
+	{
+		*error = SRC_ERR_MALLOC_FAILED ;
+		return NULL ;
+	}
 
-	temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ;
+	state->channels = channels ;
+	state->mode = SRC_MODE_PROCESS ;
 
-	if (state->channels > ARRAY_LEN (temp_filter.left_calc))
-		return SRC_ERR_BAD_CHANNEL_COUNT ;
-	else if (state->channels == 1)
-	{	state->const_process = sinc_mono_vari_process ;
+	if (state->channels == 1)
+	{
+		state->const_process = sinc_mono_vari_process ;
 		state->vari_process = sinc_mono_vari_process ;
-		}
-	else
-	if (state->channels == 2)
-	{	state->const_process = sinc_stereo_vari_process ;
+	}
+	else if (state->channels == 2)
+	{
+		state->const_process = sinc_stereo_vari_process ;
 		state->vari_process = sinc_stereo_vari_process ;
-		}
-	else
-	if (state->channels == 4)
-	{	state->const_process = sinc_quad_vari_process ;
+	}
+	else if (state->channels == 4)
+	{
+		state->const_process = sinc_quad_vari_process ;
 		state->vari_process = sinc_quad_vari_process ;
-		}
-	else
-	if (state->channels == 6)
-	{	state->const_process = sinc_hex_vari_process ;
+	}
+	else if (state->channels == 6)
+	{
+		state->const_process = sinc_hex_vari_process ;
 		state->vari_process = sinc_hex_vari_process ;
-		}
+	}
 	else
-	{	state->const_process = sinc_multichan_vari_process ;
+	{
+		state->const_process = sinc_multichan_vari_process ;
 		state->vari_process = sinc_multichan_vari_process ;
-		} ;
+	}
 	state->reset = sinc_reset ;
 	state->copy = sinc_copy ;
 	state->close = sinc_close ;
 
-	switch (src_enum)
-	{	case SRC_SINC_FASTEST :
-				temp_filter.coeffs = fastest_coeffs.coeffs ;
-				temp_filter.coeff_half_len = ARRAY_LEN (fastest_coeffs.coeffs) - 2 ;
-				temp_filter.index_inc = fastest_coeffs.increment ;
-				break ;
+	state->private_data = sinc_filter_new (converter_type, state->channels) ;
+	if (!state->private_data)
+	{
+		free (state) ;
+		*error = SRC_ERR_MALLOC_FAILED ;
+		return NULL ;
+	}
 
-		case SRC_SINC_MEDIUM_QUALITY :
-				temp_filter.coeffs = slow_mid_qual_coeffs.coeffs ;
-				temp_filter.coeff_half_len = ARRAY_LEN (slow_mid_qual_coeffs.coeffs) - 2 ;
-				temp_filter.index_inc = slow_mid_qual_coeffs.increment ;
-				break ;
-
-		case SRC_SINC_BEST_QUALITY :
-				temp_filter.coeffs = slow_high_qual_coeffs.coeffs ;
-				temp_filter.coeff_half_len = ARRAY_LEN (slow_high_qual_coeffs.coeffs) - 2 ;
-				temp_filter.index_inc = slow_high_qual_coeffs.increment ;
-				break ;
-
-		default :
-				return SRC_ERR_BAD_CONVERTER ;
-		} ;
-
-	/*
-	** FIXME : This needs to be looked at more closely to see if there is
-	** a better way. Need to look at prepare_data () at the same time.
-	*/
-
-	temp_filter.b_len = 3 * (int) lrint ((temp_filter.coeff_half_len + 2.0) / temp_filter.index_inc * SRC_MAX_RATIO + 1) ;
-	temp_filter.b_len = MAX (temp_filter.b_len, 4096) ;
-	temp_filter.b_len *= state->channels ;
-	temp_filter.b_len += 1 ; // There is a <= check against samples_in_hand requiring a buffer bigger than the calculation above
-
-	if ((filter = (SINC_FILTER *) calloc (1, sizeof (SINC_FILTER))) == NULL)
-		return SRC_ERR_MALLOC_FAILED ;
-
-	*filter = temp_filter ;
-	filter->buffer = (float *) calloc (temp_filter.b_len + state->channels, sizeof (float)) ;
-	if (!filter->buffer)
-	{	free (filter) ;
-		return SRC_ERR_MALLOC_FAILED ;
-		} ;
-
-	memset (&temp_filter, 0xEE, sizeof (temp_filter)) ;
-
-	state->private_data = filter ;
-
 	sinc_reset (state) ;
 
-	count = filter->coeff_half_len ;
-	for (bits = 0 ; (MAKE_INCREMENT_T (1) << bits) < count ; bits++)
-		count |= (MAKE_INCREMENT_T (1) << bits) ;
+	*error = SRC_ERR_NO_ERROR ;
 
-	if (bits + SHIFT_BITS - 1 >= (int) (sizeof (increment_t) * 8))
-		return SRC_ERR_FILTER_LEN ;
-
-	return SRC_ERR_NO_ERROR ;
-} /* sinc_set_converter */
+	return state ;
+}
 
 static void
 sinc_reset (SRC_STATE *state)
--- a/src/src_zoh.c
+++ b/src/src_zoh.c
@@ -6,6 +6,7 @@
 ** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
 */
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -149,37 +150,50 @@
 	return NULL ;
 } /* zoh_get_descrition */
 
-SRC_ERROR
-zoh_set_converter (SRC_STATE *state, int src_enum)
+static ZOH_DATA *
+zoh_data_new (int channels)
 {
-	ZOH_DATA *priv = NULL ;
+	assert (channels > 0) ;
 
-	if (src_enum != SRC_ZERO_ORDER_HOLD)
-		return SRC_ERR_BAD_CONVERTER ;
-
-	zoh_close (state) ;
-
-	if (state->private_data == NULL)
+	ZOH_DATA *priv = (ZOH_DATA *) calloc (1, sizeof (ZOH_DATA)) ;
+	if (priv)
 	{
-		priv = (ZOH_DATA *) calloc (1, sizeof (ZOH_DATA)) ;
-		if (priv)
+		priv->zoh_magic_marker = ZOH_MAGIC_MARKER ;
+		priv->last_value = (float *) calloc (channels, sizeof (float)) ;
+		if (!priv->last_value)
 		{
-			priv->last_value = (float *) calloc (state->channels, sizeof (float)) ;
-			if (!priv->last_value)
-			{
-				free (priv) ;
-				priv = NULL ;
-			}
+			free (priv) ;
+			priv = NULL ;
 		}
 	}
 
-	if (priv == NULL)
-		return SRC_ERR_MALLOC_FAILED ;
+	return priv ;
+}
 
-	state->private_data = priv ;
+SRC_STATE *
+zoh_state_new (int channels, SRC_ERROR *error)
+{
+	assert (channels > 0) ;
+	assert (error != NULL) ;
 
-	priv->zoh_magic_marker = ZOH_MAGIC_MARKER ;
+	SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;
+	if (!state)
+	{
+		*error = SRC_ERR_MALLOC_FAILED ;
+		return NULL ;
+	}
 
+	state->channels = channels ;
+	state->mode = SRC_MODE_PROCESS ;
+
+	state->private_data = zoh_data_new (state->channels) ;
+	if (!state->private_data)
+	{
+		free (state) ;
+		*error = SRC_ERR_MALLOC_FAILED ;
+		return NULL ;
+	}
+
 	state->const_process = zoh_vari_process ;
 	state->vari_process = zoh_vari_process ;
 	state->reset = zoh_reset ;
@@ -188,8 +202,10 @@
 
 	zoh_reset (state) ;
 
-	return SRC_ERR_NO_ERROR ;
-} /* zoh_set_converter */
+	*error = SRC_ERR_NO_ERROR ;
+
+	return state ;
+}
 
 /*===================================================================================
 */