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:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
20
src/3rdparty/samplerate/samplerate.c
vendored
20
src/3rdparty/samplerate/samplerate.c
vendored
@@ -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 ;
|
||||
|
||||
10
src/3rdparty/samplerate/samplerate.h
vendored
10
src/3rdparty/samplerate/samplerate.h
vendored
@@ -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
|
||||
|
||||
104
src/3rdparty/samplerate/src_linear.c
vendored
104
src/3rdparty/samplerate/src_linear.c
vendored
@@ -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 */
|
||||
|
||||
|
||||
868
src/3rdparty/samplerate/src_sinc.c
vendored
868
src/3rdparty/samplerate/src_sinc.c
vendored
@@ -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 */
|
||||
|
||||
|
||||
95
src/3rdparty/samplerate/src_zoh.c
vendored
95
src/3rdparty/samplerate/src_zoh.c
vendored
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user