integrated latest libsamplerate (0.1.6) which is both faster and more reliable (stable backport)

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/branches/lmms/stable-0.4@2038 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2009-02-13 16:31:01 +00:00
parent e867071e43
commit ab180ad254
7 changed files with 915 additions and 192 deletions

View File

@@ -317,7 +317,7 @@ ENDIF(LMMS_BUILD_WIN32)
# check for libsamplerate
IF(WANT_SYSTEM_SR)
PKG_CHECK_MODULES(SAMPLERATE samplerate>=0.1.3)
PKG_CHECK_MODULES(SAMPLERATE samplerate>=0.1.6)
IF(SAMPLERATE_FOUND)
SET(LMMS_HAVE_SAMPLERATE TRUE)
ENDIF(SAMPLERATE_FOUND)

View File

@@ -1,5 +1,13 @@
2009-02-13 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
* src/3rdparty/samplerate/src_linear.c:
* src/3rdparty/samplerate/samplerate.h:
* src/3rdparty/samplerate/src_sinc.c:
* src/3rdparty/samplerate/src_zoh.c:
* src/3rdparty/samplerate/samplerate.c:
* CMakeLists.txt:
integrated latest libsamplerate which is both faster and more reliable
* src/gui/widgets/visualization_widget.cpp:
disable output monitor per default and show click-hint

View File

@@ -87,7 +87,8 @@ src_callback_new (src_callback_t func, int converter_type, int channels, int *er
if (error != NULL)
*error = 0 ;
src_state = src_new (converter_type, channels, error) ;
if ((src_state = src_new (converter_type, channels, error)) == NULL)
return NULL ;
src_reset (src_state) ;
@@ -132,16 +133,13 @@ src_process (SRC_STATE *state, SRC_DATA *data)
if (data == NULL)
return SRC_ERR_BAD_DATA ;
/* Check src_ratio is in range. */
if (is_bad_src_ratio (data->src_ratio))
return SRC_ERR_BAD_SRC_RATIO ;
/* And that data_in and data_out are valid. */
if (data->data_in == NULL || data->data_out == NULL)
return SRC_ERR_BAD_DATA_PTR ;
if (data->data_in == NULL)
data->input_frames = 0 ;
/* Check src_ratio is in range. */
if (is_bad_src_ratio (data->src_ratio))
return SRC_ERR_BAD_SRC_RATIO ;
if (data->input_frames < 0)
data->input_frames = 0 ;
@@ -224,9 +222,13 @@ src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data)
output_frames_gen = 0 ;
while (output_frames_gen < frames)
{
{ /* Use a dummy array for the case where the callback function
** returns without setting the ptr.
*/
float dummy [1] ;
if (src_data.input_frames == 0)
{ float *ptr ;
{ float *ptr = dummy ;
src_data.input_frames = psrc->callback_func (psrc->user_callback_data, &ptr) ;
src_data.data_in = ptr ;

View File

@@ -30,8 +30,6 @@
#ifndef SAMPLERATE_H
#define SAMPLERATE_H
#include "export.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -75,7 +73,7 @@ typedef long (*src_callback_t) (void *cb_data, float **data) ;
** Error returned in *error.
*/
SRC_STATE* EXPORT src_new (int converter_type, int channels, int *error) ;
SRC_STATE* src_new (int converter_type, int channels, int *error) ;
/*
** Initilisation for callback based API : return an anonymous pointer to the
@@ -93,14 +91,14 @@ SRC_STATE* src_callback_new (src_callback_t func, int converter_type, int channe
** Always returns NULL.
*/
SRC_STATE* EXPORT src_delete (SRC_STATE *state) ;
SRC_STATE* src_delete (SRC_STATE *state) ;
/*
** Standard processing function.
** Returns non zero on error.
*/
int EXPORT src_process (SRC_STATE *state, SRC_DATA *data) ;
int src_process (SRC_STATE *state, SRC_DATA *data) ;
/*
** Callback based processing function. Read up to frames worth of data from
@@ -163,7 +161,7 @@ int src_error (SRC_STATE *state) ;
/*
** Convert the error number into a string.
*/
const char* EXPORT src_strerror (int error) ;
const char* src_strerror (int error) ;
/*
** The following enums can be used to set the interpolator type

View File

@@ -54,42 +54,42 @@ typedef struct
static int
linear_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ LINEAR_DATA *linear ;
{ LINEAR_DATA *priv ;
double src_ratio, input_index, rem ;
int ch ;
if (psrc->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
linear = (LINEAR_DATA*) psrc->private_data ;
priv = (LINEAR_DATA*) psrc->private_data ;
if (linear->reset)
if (priv->reset)
{ /* If we have just been reset, set the last_value data. */
for (ch = 0 ; ch < linear->channels ; ch++)
linear->last_value [ch] = data->data_in [ch] ;
linear->reset = 0 ;
for (ch = 0 ; ch < priv->channels ; ch++)
priv->last_value [ch] = data->data_in [ch] ;
priv->reset = 0 ;
} ;
linear->in_count = data->input_frames * linear->channels ;
linear->out_count = data->output_frames * linear->channels ;
linear->in_used = linear->out_gen = 0 ;
priv->in_count = data->input_frames * priv->channels ;
priv->out_count = data->output_frames * priv->channels ;
priv->in_used = priv->out_gen = 0 ;
src_ratio = psrc->last_ratio ;
input_index = psrc->last_position ;
/* Calculate samples before first sample in input array. */
while (input_index < 1.0 && linear->out_gen < linear->out_count)
while (input_index < 1.0 && priv->out_gen < priv->out_count)
{
if (linear->in_used + linear->channels * input_index > linear->in_count)
if (priv->in_used + priv->channels * (1.0 + input_index) >= priv->in_count)
break ;
if (linear->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / linear->out_count ;
if (priv->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + priv->out_gen * (data->src_ratio - psrc->last_ratio) / priv->out_count ;
for (ch = 0 ; ch < linear->channels ; ch++)
{ data->data_out [linear->out_gen] = (float) (linear->last_value [ch] + input_index *
(data->data_in [ch] - linear->last_value [ch])) ;
linear->out_gen ++ ;
for (ch = 0 ; ch < priv->channels ; ch++)
{ data->data_out [priv->out_gen] = (float) (priv->last_value [ch] + input_index *
(data->data_in [ch] - priv->last_value [ch])) ;
priv->out_gen ++ ;
} ;
/* Figure out the next index. */
@@ -97,50 +97,50 @@ linear_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
} ;
rem = fmod_one (input_index) ;
linear->in_used += linear->channels * lrint (input_index - rem) ;
priv->in_used += priv->channels * lrint (input_index - rem) ;
input_index = rem ;
/* Main processing loop. */
while (linear->out_gen < linear->out_count && linear->in_used + linear->channels * input_index <= linear->in_count)
while (priv->out_gen < priv->out_count && priv->in_used + priv->channels * input_index < priv->in_count)
{
if (linear->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / linear->out_count ;
if (priv->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + priv->out_gen * (data->src_ratio - psrc->last_ratio) / priv->out_count ;
if (SRC_DEBUG && linear->in_used < linear->channels && input_index < 1.0)
{ printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", linear->in_used, linear->channels, input_index) ;
if (SRC_DEBUG && priv->in_used < priv->channels && input_index < 1.0)
{ printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", priv->in_used, priv->channels, input_index) ;
exit (1) ;
} ;
for (ch = 0 ; ch < linear->channels ; ch++)
{ data->data_out [linear->out_gen] = (float) (data->data_in [linear->in_used - linear->channels + ch] + input_index *
(data->data_in [linear->in_used + ch] - data->data_in [linear->in_used - linear->channels + ch])) ;
linear->out_gen ++ ;
for (ch = 0 ; ch < priv->channels ; ch++)
{ data->data_out [priv->out_gen] = (float) (data->data_in [priv->in_used - priv->channels + ch] + input_index *
(data->data_in [priv->in_used + ch] - data->data_in [priv->in_used - priv->channels + ch])) ;
priv->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
linear->in_used += linear->channels * lrint (input_index - rem) ;
priv->in_used += priv->channels * lrint (input_index - rem) ;
input_index = rem ;
} ;
if (linear->in_used > linear->in_count)
{ input_index += (linear->in_used - linear->in_count) / linear->channels ;
linear->in_used = linear->in_count ;
if (priv->in_used > priv->in_count)
{ input_index += (priv->in_used - priv->in_count) / priv->channels ;
priv->in_used = priv->in_count ;
} ;
psrc->last_position = input_index ;
if (linear->in_used > 0)
for (ch = 0 ; ch < linear->channels ; ch++)
linear->last_value [ch] = data->data_in [linear->in_used - linear->channels + ch] ;
if (priv->in_used > 0)
for (ch = 0 ; ch < priv->channels ; ch++)
priv->last_value [ch] = data->data_in [priv->in_used - priv->channels + ch] ;
/* Save current ratio rather then target ratio. */
psrc->last_ratio = src_ratio ;
data->input_frames_used = linear->in_used / linear->channels ;
data->output_frames_gen = linear->out_gen / linear->channels ;
data->input_frames_used = priv->in_used / priv->channels ;
data->output_frames_gen = priv->out_gen / priv->channels ;
return SRC_ERR_NO_ERROR ;
} /* linear_vari_process */
@@ -168,28 +168,25 @@ linear_get_description (int src_enum)
int
linear_set_converter (SRC_PRIVATE *psrc, int src_enum)
{ LINEAR_DATA *linear = NULL ;
{ LINEAR_DATA *priv = NULL ;
if (src_enum != SRC_LINEAR)
return SRC_ERR_BAD_CONVERTER ;
if (psrc->private_data != NULL)
{ linear = (LINEAR_DATA*) psrc->private_data ;
if (linear->linear_magic_marker != LINEAR_MAGIC_MARKER)
{ free (psrc->private_data) ;
psrc->private_data = NULL ;
} ;
{ free (psrc->private_data) ;
psrc->private_data = NULL ;
} ;
if (psrc->private_data == NULL)
{ linear = calloc (1, sizeof (*linear) + psrc->channels * sizeof (float)) ;
if (linear == NULL)
{ priv = calloc (1, sizeof (*priv) + psrc->channels * sizeof (float)) ;
if (priv == NULL)
return SRC_ERR_MALLOC_FAILED ;
psrc->private_data = linear ;
psrc->private_data = priv ;
} ;
linear->linear_magic_marker = LINEAR_MAGIC_MARKER ;
linear->channels = psrc->channels ;
priv->linear_magic_marker = LINEAR_MAGIC_MARKER ;
priv->channels = psrc->channels ;
psrc->const_process = linear_vari_process ;
psrc->vari_process = linear_vari_process ;
@@ -205,15 +202,16 @@ linear_set_converter (SRC_PRIVATE *psrc, int src_enum)
static void
linear_reset (SRC_PRIVATE *psrc)
{ LINEAR_DATA *linear = NULL ;
{ LINEAR_DATA *priv = NULL ;
linear = (LINEAR_DATA*) psrc->private_data ;
if (linear == NULL)
priv = (LINEAR_DATA*) psrc->private_data ;
if (priv == NULL)
return ;
linear->channels = psrc->channels ;
linear->reset = 1 ;
priv->channels = psrc->channels ;
priv->reset = 1 ;
memset (priv->last_value, 0, sizeof (priv->last_value [0]) * priv->channels) ;
memset (linear->last_value, 0, sizeof (linear->last_value [0]) * linear->channels) ;
return ;
} /* linear_reset */

View File

@@ -65,12 +65,16 @@ typedef struct
coeff_t const *coeffs ;
int b_current, b_end, b_real_end, b_len ;
float buffer [1] ;
/* C99 struct flexible array. */
float buffer [] ;
} SINC_FILTER ;
static int sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static double calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch) ;
static int sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static int sinc_hex_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static int sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static int sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static int sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ;
@@ -78,9 +82,7 @@ static void sinc_reset (SRC_PRIVATE *psrc) ;
static inline increment_t
double_to_fp (double x)
{ if (sizeof (increment_t) == 8)
return (llrint ((x) * FP_ONE)) ;
return (lrint ((x) * FP_ONE)) ;
{ return (lrint ((x) * FP_ONE)) ;
} /* double_to_fp */
static inline increment_t
@@ -157,11 +159,8 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum)
return SRC_ERR_SHIFT_BITS ;
if (psrc->private_data != NULL)
{ filter = (SINC_FILTER*) psrc->private_data ;
if (filter->sinc_magic_marker != SINC_MAGIC_MARKER)
{ free (psrc->private_data) ;
psrc->private_data = NULL ;
} ;
{ free (psrc->private_data) ;
psrc->private_data = NULL ;
} ;
memset (&temp_filter, 0, sizeof (temp_filter)) ;
@@ -169,8 +168,29 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum)
temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ;
temp_filter.channels = psrc->channels ;
psrc->const_process = sinc_vari_process ;
psrc->vari_process = sinc_vari_process ;
if (psrc->channels == 1)
{ psrc->const_process = sinc_mono_vari_process ;
psrc->vari_process = sinc_mono_vari_process ;
}
else
if (psrc->channels == 2)
{ psrc->const_process = sinc_stereo_vari_process ;
psrc->vari_process = sinc_stereo_vari_process ;
}
else
if (psrc->channels == 4)
{ psrc->const_process = sinc_quad_vari_process ;
psrc->vari_process = sinc_quad_vari_process ;
}
else
if (psrc->channels == 6)
{ psrc->const_process = sinc_hex_vari_process ;
psrc->vari_process = sinc_hex_vari_process ;
}
else
{ psrc->const_process = sinc_multichan_vari_process ;
psrc->vari_process = sinc_multichan_vari_process ;
} ;
psrc->reset = sinc_reset ;
switch (src_enum)
@@ -248,12 +268,64 @@ sinc_reset (SRC_PRIVATE *psrc)
** Beware all ye who dare pass this point. There be dragons here.
*/
static inline double
calc_output_single (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index)
{ double fraction, left, right, icoeff ;
increment_t filter_index, max_filter_index ;
int data_index, coeff_count, indx ;
/* Convert input parameters into fixed point. */
max_filter_index = int_to_fp (filter->coeff_half_len) ;
/* First apply the left half of the filter. */
filter_index = start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - coeff_count ;
left = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
left += icoeff * filter->buffer [data_index] ;
filter_index -= increment ;
data_index = data_index + 1 ;
}
while (filter_index >= MAKE_INCREMENT_T (0)) ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current + 1 + coeff_count ;
right = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
right += icoeff * filter->buffer [data_index] ;
filter_index -= increment ;
data_index = data_index - 1 ;
}
while (filter_index > MAKE_INCREMENT_T (0)) ;
return (left + right) ;
} /* calc_output_single */
static int
sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ SINC_FILTER *filter ;
double input_index, src_ratio, count, float_increment, terminate, rem ;
increment_t increment, start_filter_index ;
int half_filter_chan_len, samples_in_hand, ch ;
int half_filter_chan_len, samples_in_hand ;
if (psrc->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
@@ -318,11 +390,9 @@ sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
start_filter_index = double_to_fp (input_index * float_increment) ;
for (ch = 0 ; ch < filter->channels ; ch++)
{ data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *
calc_output (filter, increment, start_filter_index, ch)) ;
filter->out_gen ++ ;
} ;
data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *
calc_output_single (filter, increment, start_filter_index)) ;
filter->out_gen ++ ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
@@ -341,7 +411,709 @@ sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
data->output_frames_gen = filter->out_gen / filter->channels ;
return SRC_ERR_NO_ERROR ;
} /* sinc_vari_process */
} /* sinc_mono_vari_process */
static inline void
calc_output_stereo (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, double scale, float * output)
{ double fraction, left [2], right [2], icoeff ;
increment_t filter_index, max_filter_index ;
int data_index, coeff_count, indx ;
/* Convert input parameters into fixed point. */
max_filter_index = int_to_fp (filter->coeff_half_len) ;
/* First apply the left half of the filter. */
filter_index = start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - filter->channels * coeff_count ;
left [0] = left [1] = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
left [0] += icoeff * filter->buffer [data_index] ;
left [1] += icoeff * filter->buffer [data_index + 1] ;
filter_index -= increment ;
data_index = data_index + 2 ;
}
while (filter_index >= MAKE_INCREMENT_T (0)) ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
right [0] = right [1] = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
right [0] += icoeff * filter->buffer [data_index] ;
right [1] += icoeff * filter->buffer [data_index + 1] ;
filter_index -= increment ;
data_index = data_index - 2 ;
}
while (filter_index > MAKE_INCREMENT_T (0)) ;
output [0] = scale * (left [0] + right [0]) ;
output [1] = scale * (left [1] + right [1]) ;
} /* calc_output_stereo */
static int
sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ SINC_FILTER *filter ;
double input_index, src_ratio, count, float_increment, terminate, rem ;
increment_t increment, start_filter_index ;
int half_filter_chan_len, samples_in_hand ;
if (psrc->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
filter = (SINC_FILTER*) psrc->private_data ;
/* If there is not a problem, this will be optimised out. */
if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
return SRC_ERR_SIZE_INCOMPATIBILITY ;
filter->in_count = data->input_frames * filter->channels ;
filter->out_count = data->output_frames * filter->channels ;
filter->in_used = filter->out_gen = 0 ;
src_ratio = psrc->last_ratio ;
/* Check the sample rate ratio wrt the buffer len. */
count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
count /= MIN (psrc->last_ratio, data->src_ratio) ;
/* Maximum coefficientson either side of center point. */
half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
input_index = psrc->last_position ;
float_increment = filter->index_inc ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
terminate = 1.0 / src_ratio + 1e-20 ;
/* Main processing loop. */
while (filter->out_gen < filter->out_count)
{
/* Need to reload buffer? */
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
{ prepare_data (filter, data, half_filter_chan_len) ;
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
break ;
} ;
/* This is the termination condition. */
if (filter->b_real_end >= 0)
{ if (filter->b_current + input_index + terminate >= filter->b_real_end)
break ;
} ;
if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
float_increment = filter->index_inc * 1.0 ;
if (src_ratio < 1.0)
float_increment = filter->index_inc * src_ratio ;
increment = double_to_fp (float_increment) ;
start_filter_index = double_to_fp (input_index * float_increment) ;
calc_output_stereo (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
filter->out_gen += 2 ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
} ;
psrc->last_position = input_index ;
/* Save current ratio rather then target ratio. */
psrc->last_ratio = src_ratio ;
data->input_frames_used = filter->in_used / filter->channels ;
data->output_frames_gen = filter->out_gen / filter->channels ;
return SRC_ERR_NO_ERROR ;
} /* sinc_stereo_vari_process */
static inline void
calc_output_quad (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, double scale, float * output)
{ double fraction, left [4], right [4], icoeff ;
increment_t filter_index, max_filter_index ;
int data_index, coeff_count, indx ;
/* Convert input parameters into fixed point. */
max_filter_index = int_to_fp (filter->coeff_half_len) ;
/* First apply the left half of the filter. */
filter_index = start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - filter->channels * coeff_count ;
left [0] = left [1] = left [2] = left [3] = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
left [0] += icoeff * filter->buffer [data_index] ;
left [1] += icoeff * filter->buffer [data_index + 1] ;
left [2] += icoeff * filter->buffer [data_index + 2] ;
left [3] += icoeff * filter->buffer [data_index + 3] ;
filter_index -= increment ;
data_index = data_index + 4 ;
}
while (filter_index >= MAKE_INCREMENT_T (0)) ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
right [0] = right [1] = right [2] = right [3] = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
right [0] += icoeff * filter->buffer [data_index] ;
right [1] += icoeff * filter->buffer [data_index + 1] ;
right [2] += icoeff * filter->buffer [data_index + 2] ;
right [3] += icoeff * filter->buffer [data_index + 3] ;
filter_index -= increment ;
data_index = data_index - 4 ;
}
while (filter_index > MAKE_INCREMENT_T (0)) ;
output [0] = scale * (left [0] + right [0]) ;
output [1] = scale * (left [1] + right [1]) ;
output [2] = scale * (left [2] + right [2]) ;
output [3] = scale * (left [3] + right [3]) ;
} /* calc_output_quad */
static int
sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ SINC_FILTER *filter ;
double input_index, src_ratio, count, float_increment, terminate, rem ;
increment_t increment, start_filter_index ;
int half_filter_chan_len, samples_in_hand ;
if (psrc->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
filter = (SINC_FILTER*) psrc->private_data ;
/* If there is not a problem, this will be optimised out. */
if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
return SRC_ERR_SIZE_INCOMPATIBILITY ;
filter->in_count = data->input_frames * filter->channels ;
filter->out_count = data->output_frames * filter->channels ;
filter->in_used = filter->out_gen = 0 ;
src_ratio = psrc->last_ratio ;
/* Check the sample rate ratio wrt the buffer len. */
count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
count /= MIN (psrc->last_ratio, data->src_ratio) ;
/* Maximum coefficientson either side of center point. */
half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
input_index = psrc->last_position ;
float_increment = filter->index_inc ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
terminate = 1.0 / src_ratio + 1e-20 ;
/* Main processing loop. */
while (filter->out_gen < filter->out_count)
{
/* Need to reload buffer? */
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
{ prepare_data (filter, data, half_filter_chan_len) ;
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
break ;
} ;
/* This is the termination condition. */
if (filter->b_real_end >= 0)
{ if (filter->b_current + input_index + terminate >= filter->b_real_end)
break ;
} ;
if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
float_increment = filter->index_inc * 1.0 ;
if (src_ratio < 1.0)
float_increment = filter->index_inc * src_ratio ;
increment = double_to_fp (float_increment) ;
start_filter_index = double_to_fp (input_index * float_increment) ;
calc_output_quad (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
filter->out_gen += 4 ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
} ;
psrc->last_position = input_index ;
/* Save current ratio rather then target ratio. */
psrc->last_ratio = src_ratio ;
data->input_frames_used = filter->in_used / filter->channels ;
data->output_frames_gen = filter->out_gen / filter->channels ;
return SRC_ERR_NO_ERROR ;
} /* sinc_quad_vari_process */
static inline void
calc_output_hex (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, double scale, float * output)
{ double fraction, left [6], right [6], icoeff ;
increment_t filter_index, max_filter_index ;
int data_index, coeff_count, indx ;
/* Convert input parameters into fixed point. */
max_filter_index = int_to_fp (filter->coeff_half_len) ;
/* First apply the left half of the filter. */
filter_index = start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - filter->channels * coeff_count ;
left [0] = left [1] = left [2] = left [3] = left [4] = left [5] = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
left [0] += icoeff * filter->buffer [data_index] ;
left [1] += icoeff * filter->buffer [data_index + 1] ;
left [2] += icoeff * filter->buffer [data_index + 2] ;
left [3] += icoeff * filter->buffer [data_index + 3] ;
left [4] += icoeff * filter->buffer [data_index + 4] ;
left [5] += icoeff * filter->buffer [data_index + 5] ;
filter_index -= increment ;
data_index = data_index + 6 ;
}
while (filter_index >= MAKE_INCREMENT_T (0)) ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
right [0] = right [1] = right [2] = right [3] = right [4] = right [5] = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
right [0] += icoeff * filter->buffer [data_index] ;
right [1] += icoeff * filter->buffer [data_index + 1] ;
right [2] += icoeff * filter->buffer [data_index + 2] ;
right [3] += icoeff * filter->buffer [data_index + 3] ;
right [4] += icoeff * filter->buffer [data_index + 4] ;
right [5] += icoeff * filter->buffer [data_index + 5] ;
filter_index -= increment ;
data_index = data_index - 6 ;
}
while (filter_index > MAKE_INCREMENT_T (0)) ;
output [0] = scale * (left [0] + right [0]) ;
output [1] = scale * (left [1] + right [1]) ;
output [2] = scale * (left [2] + right [2]) ;
output [3] = scale * (left [3] + right [3]) ;
output [4] = scale * (left [4] + right [4]) ;
output [5] = scale * (left [5] + right [5]) ;
} /* calc_output_hex */
static int
sinc_hex_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ SINC_FILTER *filter ;
double input_index, src_ratio, count, float_increment, terminate, rem ;
increment_t increment, start_filter_index ;
int half_filter_chan_len, samples_in_hand ;
if (psrc->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
filter = (SINC_FILTER*) psrc->private_data ;
/* If there is not a problem, this will be optimised out. */
if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
return SRC_ERR_SIZE_INCOMPATIBILITY ;
filter->in_count = data->input_frames * filter->channels ;
filter->out_count = data->output_frames * filter->channels ;
filter->in_used = filter->out_gen = 0 ;
src_ratio = psrc->last_ratio ;
/* Check the sample rate ratio wrt the buffer len. */
count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
count /= MIN (psrc->last_ratio, data->src_ratio) ;
/* Maximum coefficientson either side of center point. */
half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
input_index = psrc->last_position ;
float_increment = filter->index_inc ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
terminate = 1.0 / src_ratio + 1e-20 ;
/* Main processing loop. */
while (filter->out_gen < filter->out_count)
{
/* Need to reload buffer? */
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
{ prepare_data (filter, data, half_filter_chan_len) ;
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
break ;
} ;
/* This is the termination condition. */
if (filter->b_real_end >= 0)
{ if (filter->b_current + input_index + terminate >= filter->b_real_end)
break ;
} ;
if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
float_increment = filter->index_inc * 1.0 ;
if (src_ratio < 1.0)
float_increment = filter->index_inc * src_ratio ;
increment = double_to_fp (float_increment) ;
start_filter_index = double_to_fp (input_index * float_increment) ;
calc_output_hex (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
filter->out_gen += 6 ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
} ;
psrc->last_position = input_index ;
/* Save current ratio rather then target ratio. */
psrc->last_ratio = src_ratio ;
data->input_frames_used = filter->in_used / filter->channels ;
data->output_frames_gen = filter->out_gen / filter->channels ;
return SRC_ERR_NO_ERROR ;
} /* sinc_hex_vari_process */
static inline void
calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int channels, double scale, float * output)
{ double fraction, icoeff ;
/* The following line is 1999 ISO Standard C. If your compiler complains, get a better compiler. */
double left [channels], right [channels] ;
increment_t filter_index, max_filter_index ;
int data_index, coeff_count, indx, ch ;
/* Convert input parameters into fixed point. */
max_filter_index = int_to_fp (filter->coeff_half_len) ;
/* First apply the left half of the filter. */
filter_index = start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - channels * coeff_count ;
memset (left, 0, sizeof (left)) ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
/*
** Duff's Device.
** See : http://en.wikipedia.org/wiki/Duff's_device
*/
ch = channels ;
do
{
switch (ch % 8)
{ default :
ch -- ;
left [ch] += icoeff * filter->buffer [data_index + ch] ;
case 7 :
ch -- ;
left [ch] += icoeff * filter->buffer [data_index + ch] ;
case 6 :
ch -- ;
left [ch] += icoeff * filter->buffer [data_index + ch] ;
case 5 :
ch -- ;
left [ch] += icoeff * filter->buffer [data_index + ch] ;
case 4 :
ch -- ;
left [ch] += icoeff * filter->buffer [data_index + ch] ;
case 3 :
ch -- ;
left [ch] += icoeff * filter->buffer [data_index + ch] ;
case 2 :
ch -- ;
left [ch] += icoeff * filter->buffer [data_index + ch] ;
case 1 :
ch -- ;
left [ch] += icoeff * filter->buffer [data_index + ch] ;
} ;
}
while (ch > 0) ;
filter_index -= increment ;
data_index = data_index + channels ;
}
while (filter_index >= MAKE_INCREMENT_T (0)) ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current + channels * (1 + coeff_count) ;
memset (right, 0, sizeof (right)) ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
ch = channels ;
do
{
switch (ch % 8)
{ default :
ch -- ;
right [ch] += icoeff * filter->buffer [data_index + ch] ;
case 7 :
ch -- ;
right [ch] += icoeff * filter->buffer [data_index + ch] ;
case 6 :
ch -- ;
right [ch] += icoeff * filter->buffer [data_index + ch] ;
case 5 :
ch -- ;
right [ch] += icoeff * filter->buffer [data_index + ch] ;
case 4 :
ch -- ;
right [ch] += icoeff * filter->buffer [data_index + ch] ;
case 3 :
ch -- ;
right [ch] += icoeff * filter->buffer [data_index + ch] ;
case 2 :
ch -- ;
right [ch] += icoeff * filter->buffer [data_index + ch] ;
case 1 :
ch -- ;
right [ch] += icoeff * filter->buffer [data_index + ch] ;
} ;
}
while (ch > 0) ;
filter_index -= increment ;
data_index = data_index - channels ;
}
while (filter_index > MAKE_INCREMENT_T (0)) ;
ch = channels ;
do
{
switch (ch % 8)
{ default :
ch -- ;
output [ch] = scale * (left [ch] + right [ch]) ;
case 7 :
ch -- ;
output [ch] = scale * (left [ch] + right [ch]) ;
case 6 :
ch -- ;
output [ch] = scale * (left [ch] + right [ch]) ;
case 5 :
ch -- ;
output [ch] = scale * (left [ch] + right [ch]) ;
case 4 :
ch -- ;
output [ch] = scale * (left [ch] + right [ch]) ;
case 3 :
ch -- ;
output [ch] = scale * (left [ch] + right [ch]) ;
case 2 :
ch -- ;
output [ch] = scale * (left [ch] + right [ch]) ;
case 1 :
ch -- ;
output [ch] = scale * (left [ch] + right [ch]) ;
} ;
}
while (ch > 0) ;
return ;
} /* calc_output_multi */
static int
sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ SINC_FILTER *filter ;
double input_index, src_ratio, count, float_increment, terminate, rem ;
increment_t increment, start_filter_index ;
int half_filter_chan_len, samples_in_hand ;
if (psrc->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
filter = (SINC_FILTER*) psrc->private_data ;
/* If there is not a problem, this will be optimised out. */
if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
return SRC_ERR_SIZE_INCOMPATIBILITY ;
filter->in_count = data->input_frames * filter->channels ;
filter->out_count = data->output_frames * filter->channels ;
filter->in_used = filter->out_gen = 0 ;
src_ratio = psrc->last_ratio ;
/* Check the sample rate ratio wrt the buffer len. */
count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
count /= MIN (psrc->last_ratio, data->src_ratio) ;
/* Maximum coefficientson either side of center point. */
half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
input_index = psrc->last_position ;
float_increment = filter->index_inc ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
terminate = 1.0 / src_ratio + 1e-20 ;
/* Main processing loop. */
while (filter->out_gen < filter->out_count)
{
/* Need to reload buffer? */
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
{ prepare_data (filter, data, half_filter_chan_len) ;
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
if (samples_in_hand <= half_filter_chan_len)
break ;
} ;
/* This is the termination condition. */
if (filter->b_real_end >= 0)
{ if (filter->b_current + input_index + terminate >= filter->b_real_end)
break ;
} ;
if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
float_increment = filter->index_inc * 1.0 ;
if (src_ratio < 1.0)
float_increment = filter->index_inc * src_ratio ;
increment = double_to_fp (float_increment) ;
start_filter_index = double_to_fp (input_index * float_increment) ;
calc_output_multi (filter, increment, start_filter_index, filter->channels, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
filter->out_gen += psrc->channels ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
} ;
psrc->last_position = input_index ;
/* Save current ratio rather then target ratio. */
psrc->last_ratio = src_ratio ;
data->input_frames_used = filter->in_used / filter->channels ;
data->output_frames_gen = filter->out_gen / filter->channels ;
return SRC_ERR_NO_ERROR ;
} /* sinc_multichan_vari_process */
/*----------------------------------------------------------------------------------------
*/
@@ -414,55 +1186,3 @@ prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len)
} /* prepare_data */
static double
calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch)
{ double fraction, left, right, icoeff ;
increment_t filter_index, max_filter_index ;
int data_index, coeff_count, indx ;
/* Convert input parameters into fixed point. */
max_filter_index = int_to_fp (filter->coeff_half_len) ;
/* First apply the left half of the filter. */
filter_index = start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - filter->channels * coeff_count + ch ;
left = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
left += icoeff * filter->buffer [data_index] ;
filter_index -= increment ;
data_index = data_index + filter->channels ;
}
while (filter_index >= MAKE_INCREMENT_T (0)) ;
/* Now apply the right half of the filter. */
filter_index = increment - start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current + filter->channels * (1 + coeff_count) + ch ;
right = 0.0 ;
do
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
right += icoeff * filter->buffer [data_index] ;
filter_index -= increment ;
data_index = data_index - filter->channels ;
}
while (filter_index > MAKE_INCREMENT_T (0)) ;
return (left + right) ;
} /* calc_output */

View File

@@ -52,41 +52,41 @@ typedef struct
static int
zoh_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ ZOH_DATA *zoh ;
{ ZOH_DATA *priv ;
double src_ratio, input_index, rem ;
int ch ;
if (psrc->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
zoh = (ZOH_DATA*) psrc->private_data ;
priv = (ZOH_DATA*) psrc->private_data ;
if (zoh->reset)
if (priv->reset)
{ /* If we have just been reset, set the last_value data. */
for (ch = 0 ; ch < zoh->channels ; ch++)
zoh->last_value [ch] = data->data_in [ch] ;
zoh->reset = 0 ;
for (ch = 0 ; ch < priv->channels ; ch++)
priv->last_value [ch] = data->data_in [ch] ;
priv->reset = 0 ;
} ;
zoh->in_count = data->input_frames * zoh->channels ;
zoh->out_count = data->output_frames * zoh->channels ;
zoh->in_used = zoh->out_gen = 0 ;
priv->in_count = data->input_frames * priv->channels ;
priv->out_count = data->output_frames * priv->channels ;
priv->in_used = priv->out_gen = 0 ;
src_ratio = psrc->last_ratio ;
input_index = psrc->last_position ;
/* Calculate samples before first sample in input array. */
while (input_index < 1.0 && zoh->out_gen < zoh->out_count)
while (input_index < 1.0 && priv->out_gen < priv->out_count)
{
if (zoh->in_used + zoh->channels * input_index >= zoh->in_count)
if (priv->in_used + priv->channels * input_index >= priv->in_count)
break ;
if (zoh->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / zoh->out_count ;
if (priv->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + priv->out_gen * (data->src_ratio - psrc->last_ratio) / priv->out_count ;
for (ch = 0 ; ch < zoh->channels ; ch++)
{ data->data_out [zoh->out_gen] = zoh->last_value [ch] ;
zoh->out_gen ++ ;
for (ch = 0 ; ch < priv->channels ; ch++)
{ data->data_out [priv->out_gen] = priv->last_value [ch] ;
priv->out_gen ++ ;
} ;
/* Figure out the next index. */
@@ -94,44 +94,44 @@ zoh_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
} ;
rem = fmod_one (input_index) ;
zoh->in_used += zoh->channels * lrint (input_index - rem) ;
priv->in_used += priv->channels * lrint (input_index - rem) ;
input_index = rem ;
/* Main processing loop. */
while (zoh->out_gen < zoh->out_count && zoh->in_used + zoh->channels * input_index <= zoh->in_count)
while (priv->out_gen < priv->out_count && priv->in_used + priv->channels * input_index <= priv->in_count)
{
if (zoh->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / zoh->out_count ;
if (priv->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + priv->out_gen * (data->src_ratio - psrc->last_ratio) / priv->out_count ;
for (ch = 0 ; ch < zoh->channels ; ch++)
{ data->data_out [zoh->out_gen] = data->data_in [zoh->in_used - zoh->channels + ch] ;
zoh->out_gen ++ ;
for (ch = 0 ; ch < priv->channels ; ch++)
{ data->data_out [priv->out_gen] = data->data_in [priv->in_used - priv->channels + ch] ;
priv->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
zoh->in_used += zoh->channels * lrint (input_index - rem) ;
priv->in_used += priv->channels * lrint (input_index - rem) ;
input_index = rem ;
} ;
if (zoh->in_used > zoh->in_count)
{ input_index += (zoh->in_used - zoh->in_count) / zoh->channels ;
zoh->in_used = zoh->in_count ;
if (priv->in_used > priv->in_count)
{ input_index += (priv->in_used - priv->in_count) / priv->channels ;
priv->in_used = priv->in_count ;
} ;
psrc->last_position = input_index ;
if (zoh->in_used > 0)
for (ch = 0 ; ch < zoh->channels ; ch++)
zoh->last_value [ch] = data->data_in [zoh->in_used - zoh->channels + ch] ;
if (priv->in_used > 0)
for (ch = 0 ; ch < priv->channels ; ch++)
priv->last_value [ch] = data->data_in [priv->in_used - priv->channels + ch] ;
/* Save current ratio rather then target ratio. */
psrc->last_ratio = src_ratio ;
data->input_frames_used = zoh->in_used / zoh->channels ;
data->output_frames_gen = zoh->out_gen / zoh->channels ;
data->input_frames_used = priv->in_used / priv->channels ;
data->output_frames_gen = priv->out_gen / priv->channels ;
return SRC_ERR_NO_ERROR ;
} /* zoh_vari_process */
@@ -159,28 +159,25 @@ zoh_get_description (int src_enum)
int
zoh_set_converter (SRC_PRIVATE *psrc, int src_enum)
{ ZOH_DATA *zoh = NULL ;
{ ZOH_DATA *priv = NULL ;
if (src_enum != SRC_ZERO_ORDER_HOLD)
return SRC_ERR_BAD_CONVERTER ;
if (psrc->private_data != NULL)
{ zoh = (ZOH_DATA*) psrc->private_data ;
if (zoh->zoh_magic_marker != ZOH_MAGIC_MARKER)
{ free (psrc->private_data) ;
psrc->private_data = NULL ;
} ;
{ free (psrc->private_data) ;
psrc->private_data = NULL ;
} ;
if (psrc->private_data == NULL)
{ zoh = calloc (1, sizeof (*zoh) + psrc->channels * sizeof (float)) ;
if (zoh == NULL)
{ priv = calloc (1, sizeof (*priv) + psrc->channels * sizeof (float)) ;
if (priv == NULL)
return SRC_ERR_MALLOC_FAILED ;
psrc->private_data = zoh ;
psrc->private_data = priv ;
} ;
zoh->zoh_magic_marker = ZOH_MAGIC_MARKER ;
zoh->channels = psrc->channels ;
priv->zoh_magic_marker = ZOH_MAGIC_MARKER ;
priv->channels = psrc->channels ;
psrc->const_process = zoh_vari_process ;
psrc->vari_process = zoh_vari_process ;
@@ -196,15 +193,15 @@ zoh_set_converter (SRC_PRIVATE *psrc, int src_enum)
static void
zoh_reset (SRC_PRIVATE *psrc)
{ ZOH_DATA *zoh ;
{ ZOH_DATA *priv ;
zoh = (ZOH_DATA*) psrc->private_data ;
if (zoh == NULL)
priv = (ZOH_DATA*) psrc->private_data ;
if (priv == NULL)
return ;
zoh->channels = psrc->channels ;
zoh->reset = 1 ;
memset (zoh->last_value, 0, sizeof (zoh->last_value [0]) * zoh->channels) ;
priv->channels = psrc->channels ;
priv->reset = 1 ;
memset (priv->last_value, 0, sizeof (priv->last_value [0]) * priv->channels) ;
return ;
} /* zoh_reset */