mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-04 16:39:39 +00:00
audioresample: sinc filter performance improvements
Original idea comes from Jyri Sarha ( http://lists.xiph.org/pipermail/speex-dev/2011-September/008243.html ). Patch was discovered by Branislav Katreniak ( branislav.katreniak@streamunlimited.com ) for StreamUnlimited ( http://streamunlimited.com/ ). Tests showed up to 5x speed increase in the resampler in the 44.1<->48kHz case. I added the sinc-filter-mode and sinc-filter-auto-threshold properties and the auto mode threshold tests, and adapted the code to GStreamer 1.0. Signed-off-by: Carlos Rafael Giani <dv@pseudoterminal.org>
This commit is contained in:
parent
d8b42ae80c
commit
c41faa3d8e
5 changed files with 222 additions and 19 deletions
|
@ -25,6 +25,14 @@
|
||||||
* audioresample resamples raw audio buffers to different sample rates using
|
* audioresample resamples raw audio buffers to different sample rates using
|
||||||
* a configurable windowing function to enhance quality.
|
* a configurable windowing function to enhance quality.
|
||||||
*
|
*
|
||||||
|
* By default, the resampler uses a reduced sinc table, with cubic interpolation filling in
|
||||||
|
* the gaps. This ensures that the table does not become too big. However, the interpolation
|
||||||
|
* increases the CPU usage considerably. As an alternative, a full sinc table can be used.
|
||||||
|
* Doing so can drastically reduce CPU usage (4x faster with 44.1 -> 48 kHz conversions for
|
||||||
|
* example), at the cost of increased memory consumption, plus the sinc table takes longer
|
||||||
|
* to initialize when the element is created. A third mode exists, which uses the full table
|
||||||
|
* unless said table would become too large, in which case the interpolated one is used instead.
|
||||||
|
*
|
||||||
* <refsect2>
|
* <refsect2>
|
||||||
* <title>Example launch line</title>
|
* <title>Example launch line</title>
|
||||||
* |[
|
* |[
|
||||||
|
@ -62,10 +70,14 @@ GST_DEBUG_CATEGORY (audio_resample_debug);
|
||||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
|
GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define GST_TYPE_SPEEX_RESAMPLER_SINC_FILTER_MODE (speex_resampler_sinc_filter_mode_get_type ())
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_QUALITY
|
PROP_QUALITY,
|
||||||
|
PROP_SINC_FILTER_MODE,
|
||||||
|
PROP_SINC_FILTER_AUTO_THRESHOLD
|
||||||
};
|
};
|
||||||
|
|
||||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
@ -104,6 +116,9 @@ static void gst_audio_resample_set_property (GObject * object,
|
||||||
static void gst_audio_resample_get_property (GObject * object,
|
static void gst_audio_resample_get_property (GObject * object,
|
||||||
guint prop_id, GValue * value, GParamSpec * pspec);
|
guint prop_id, GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static GType
|
||||||
|
speex_resampler_sinc_filter_mode_get_type (void);
|
||||||
|
|
||||||
/* vmethods */
|
/* vmethods */
|
||||||
static gboolean gst_audio_resample_get_unit_size (GstBaseTransform * base,
|
static gboolean gst_audio_resample_get_unit_size (GstBaseTransform * base,
|
||||||
GstCaps * caps, gsize * size);
|
GstCaps * caps, gsize * size);
|
||||||
|
@ -144,6 +159,20 @@ gst_audio_resample_class_init (GstAudioResampleClass * klass)
|
||||||
SPEEX_RESAMPLER_QUALITY_DEFAULT,
|
SPEEX_RESAMPLER_QUALITY_DEFAULT,
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_SINC_FILTER_MODE,
|
||||||
|
g_param_spec_enum ("sinc-filter-mode", "Sinc filter table mode",
|
||||||
|
"What sinc filter table mode to use",
|
||||||
|
GST_TYPE_SPEEX_RESAMPLER_SINC_FILTER_MODE,
|
||||||
|
SPEEX_RESAMPLER_SINC_FILTER_DEFAULT,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_SINC_FILTER_AUTO_THRESHOLD,
|
||||||
|
g_param_spec_uint ("sinc-filter-auto-threshold", "Sinc filter auto mode threshold",
|
||||||
|
"Memory usage threshold to use if sinc filter mode is AUTO, given in bytes",
|
||||||
|
0, G_MAXUINT,
|
||||||
|
SPEEX_RESAMPLER_SINC_FILTER_AUTO_THRESHOLD_DEFAULT,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
gst_element_class_add_pad_template (gstelement_class,
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
gst_static_pad_template_get (&gst_audio_resample_src_template));
|
gst_static_pad_template_get (&gst_audio_resample_src_template));
|
||||||
gst_element_class_add_pad_template (gstelement_class,
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
@ -181,6 +210,8 @@ gst_audio_resample_init (GstAudioResample * resample)
|
||||||
GstBaseTransform *trans = GST_BASE_TRANSFORM (resample);
|
GstBaseTransform *trans = GST_BASE_TRANSFORM (resample);
|
||||||
|
|
||||||
resample->quality = SPEEX_RESAMPLER_QUALITY_DEFAULT;
|
resample->quality = SPEEX_RESAMPLER_QUALITY_DEFAULT;
|
||||||
|
resample->sinc_filter_mode = SPEEX_RESAMPLER_SINC_FILTER_DEFAULT;
|
||||||
|
resample->sinc_filter_auto_threshold = SPEEX_RESAMPLER_SINC_FILTER_AUTO_THRESHOLD_DEFAULT;
|
||||||
|
|
||||||
gst_base_transform_set_gap_aware (trans, TRUE);
|
gst_base_transform_set_gap_aware (trans, TRUE);
|
||||||
gst_pad_set_query_function (trans->srcpad, gst_audio_resample_query);
|
gst_pad_set_query_function (trans->srcpad, gst_audio_resample_query);
|
||||||
|
@ -349,13 +380,16 @@ gst_audio_resample_get_funcs (gint width, gboolean fp)
|
||||||
|
|
||||||
static SpeexResamplerState *
|
static SpeexResamplerState *
|
||||||
gst_audio_resample_init_state (GstAudioResample * resample, gint width,
|
gst_audio_resample_init_state (GstAudioResample * resample, gint width,
|
||||||
gint channels, gint inrate, gint outrate, gint quality, gboolean fp)
|
gint channels, gint inrate, gint outrate, gint quality, gboolean fp,
|
||||||
|
SpeexResamplerSincFilterMode sinc_filter_mode,
|
||||||
|
guint32 sinc_filter_auto_threshold)
|
||||||
{
|
{
|
||||||
SpeexResamplerState *ret = NULL;
|
SpeexResamplerState *ret = NULL;
|
||||||
gint err = RESAMPLER_ERR_SUCCESS;
|
gint err = RESAMPLER_ERR_SUCCESS;
|
||||||
const SpeexResampleFuncs *funcs = gst_audio_resample_get_funcs (width, fp);
|
const SpeexResampleFuncs *funcs = gst_audio_resample_get_funcs (width, fp);
|
||||||
|
|
||||||
ret = funcs->init (channels, inrate, outrate, quality, &err);
|
ret = funcs->init (channels, inrate, outrate, quality,
|
||||||
|
sinc_filter_mode, sinc_filter_auto_threshold, &err);
|
||||||
|
|
||||||
if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
|
if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
|
||||||
GST_ERROR_OBJECT (resample, "Failed to create resampler state: %s",
|
GST_ERROR_OBJECT (resample, "Failed to create resampler state: %s",
|
||||||
|
@ -363,6 +397,11 @@ gst_audio_resample_init_state (GstAudioResample * resample, gint width,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sinc_filter_mode == SPEEX_RESAMPLER_SINC_FILTER_AUTO) {
|
||||||
|
GST_INFO_OBJECT (resample, "Using the %s sinc filter table",
|
||||||
|
funcs->get_sinc_filter_mode(ret) ? "full" : "interpolated");
|
||||||
|
}
|
||||||
|
|
||||||
funcs->skip_zeros (ret);
|
funcs->skip_zeros (ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -370,7 +409,9 @@ gst_audio_resample_init_state (GstAudioResample * resample, gint width,
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_audio_resample_update_state (GstAudioResample * resample, gint width,
|
gst_audio_resample_update_state (GstAudioResample * resample, gint width,
|
||||||
gint channels, gint inrate, gint outrate, gint quality, gboolean fp)
|
gint channels, gint inrate, gint outrate, gint quality, gboolean fp,
|
||||||
|
SpeexResamplerSincFilterMode sinc_filter_mode,
|
||||||
|
guint32 sinc_filter_auto_threshold)
|
||||||
{
|
{
|
||||||
gboolean ret = TRUE;
|
gboolean ret = TRUE;
|
||||||
gboolean updated_latency = FALSE;
|
gboolean updated_latency = FALSE;
|
||||||
|
@ -381,11 +422,12 @@ gst_audio_resample_update_state (GstAudioResample * resample, gint width,
|
||||||
if (resample->state == NULL) {
|
if (resample->state == NULL) {
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
} else if (resample->channels != channels || fp != resample->fp
|
} else if (resample->channels != channels || fp != resample->fp
|
||||||
|| width != resample->width) {
|
|| width != resample->width || sinc_filter_mode != resample->sinc_filter_mode
|
||||||
|
|| sinc_filter_auto_threshold != resample->sinc_filter_auto_threshold) {
|
||||||
resample->funcs->destroy (resample->state);
|
resample->funcs->destroy (resample->state);
|
||||||
resample->state =
|
resample->state =
|
||||||
gst_audio_resample_init_state (resample, width, channels, inrate,
|
gst_audio_resample_init_state (resample, width, channels, inrate,
|
||||||
outrate, quality, fp);
|
outrate, quality, fp, sinc_filter_mode, sinc_filter_auto_threshold);
|
||||||
|
|
||||||
resample->funcs = gst_audio_resample_get_funcs (width, fp);
|
resample->funcs = gst_audio_resample_get_funcs (width, fp);
|
||||||
ret = (resample->state != NULL);
|
ret = (resample->state != NULL);
|
||||||
|
@ -417,6 +459,8 @@ gst_audio_resample_update_state (GstAudioResample * resample, gint width,
|
||||||
resample->quality = quality;
|
resample->quality = quality;
|
||||||
resample->inrate = inrate;
|
resample->inrate = inrate;
|
||||||
resample->outrate = outrate;
|
resample->outrate = outrate;
|
||||||
|
resample->sinc_filter_mode = sinc_filter_mode;
|
||||||
|
resample->sinc_filter_auto_threshold = sinc_filter_auto_threshold;
|
||||||
|
|
||||||
if (updated_latency)
|
if (updated_latency)
|
||||||
gst_element_post_message (GST_ELEMENT (resample),
|
gst_element_post_message (GST_ELEMENT (resample),
|
||||||
|
@ -526,7 +570,8 @@ gst_audio_resample_set_caps (GstBaseTransform * base, GstCaps * incaps,
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
gst_audio_resample_update_state (resample, width, channels, inrate,
|
gst_audio_resample_update_state (resample, width, channels, inrate,
|
||||||
outrate, resample->quality, fp);
|
outrate, resample->quality, fp, resample->sinc_filter_mode,
|
||||||
|
resample->sinc_filter_auto_threshold);
|
||||||
|
|
||||||
if (G_UNLIKELY (!ret))
|
if (G_UNLIKELY (!ret))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1126,7 +1171,8 @@ gst_audio_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
|
||||||
if (G_UNLIKELY (!(resample->state =
|
if (G_UNLIKELY (!(resample->state =
|
||||||
gst_audio_resample_init_state (resample, resample->width,
|
gst_audio_resample_init_state (resample, resample->width,
|
||||||
resample->channels, resample->inrate, resample->outrate,
|
resample->channels, resample->inrate, resample->outrate,
|
||||||
resample->quality, resample->fp))))
|
resample->quality, resample->fp, resample->sinc_filter_mode,
|
||||||
|
resample->sinc_filter_auto_threshold))))
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
|
|
||||||
resample->funcs =
|
resample->funcs =
|
||||||
|
@ -1279,8 +1325,31 @@ gst_audio_resample_set_property (GObject * object, guint prop_id,
|
||||||
|
|
||||||
gst_audio_resample_update_state (resample, resample->width,
|
gst_audio_resample_update_state (resample, resample->width,
|
||||||
resample->channels, resample->inrate, resample->outrate,
|
resample->channels, resample->inrate, resample->outrate,
|
||||||
quality, resample->fp);
|
quality, resample->fp, resample->sinc_filter_mode,
|
||||||
|
resample->sinc_filter_auto_threshold);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SINC_FILTER_MODE: {
|
||||||
|
/* FIXME locking! */
|
||||||
|
SpeexResamplerSincFilterMode sinc_filter_mode = g_value_get_enum (value);
|
||||||
|
|
||||||
|
gst_audio_resample_update_state (resample, resample->width,
|
||||||
|
resample->channels, resample->inrate, resample->outrate,
|
||||||
|
resample->quality, resample->fp, sinc_filter_mode,
|
||||||
|
resample->sinc_filter_auto_threshold);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PROP_SINC_FILTER_AUTO_THRESHOLD: {
|
||||||
|
/* FIXME locking! */
|
||||||
|
guint32 sinc_filter_auto_threshold = g_value_get_uint (value);
|
||||||
|
|
||||||
|
gst_audio_resample_update_state (resample, resample->width,
|
||||||
|
resample->channels, resample->inrate, resample->outrate,
|
||||||
|
resample->quality, resample->fp, resample->sinc_filter_mode,
|
||||||
|
sinc_filter_auto_threshold);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -1299,12 +1368,39 @@ gst_audio_resample_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_QUALITY:
|
case PROP_QUALITY:
|
||||||
g_value_set_int (value, resample->quality);
|
g_value_set_int (value, resample->quality);
|
||||||
break;
|
break;
|
||||||
|
case PROP_SINC_FILTER_MODE:
|
||||||
|
g_value_set_enum(value, resample->sinc_filter_mode);
|
||||||
|
break;
|
||||||
|
case PROP_SINC_FILTER_AUTO_THRESHOLD:
|
||||||
|
g_value_set_uint(value, resample->sinc_filter_auto_threshold);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GType
|
||||||
|
speex_resampler_sinc_filter_mode_get_type (void)
|
||||||
|
{
|
||||||
|
static GType speex_resampler_sinc_filter_mode_type = 0;
|
||||||
|
|
||||||
|
if (!speex_resampler_sinc_filter_mode_type) {
|
||||||
|
static GEnumValue sinc_filter_modes[] = {
|
||||||
|
{ SPEEX_RESAMPLER_SINC_FILTER_INTERPOLATED, "Use interpolated sinc table", "interpolated" },
|
||||||
|
{ SPEEX_RESAMPLER_SINC_FILTER_FULL, "Use full sinc table", "full" },
|
||||||
|
{ SPEEX_RESAMPLER_SINC_FILTER_AUTO, "Use full table if table size below threshold", "auto" },
|
||||||
|
{ 0, NULL, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
speex_resampler_sinc_filter_mode_type = g_enum_register_static (
|
||||||
|
"SpeexResamplerSincFilterMode",
|
||||||
|
sinc_filter_modes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return speex_resampler_sinc_filter_mode_type;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: should have a benchmark fallback for the case where orc is disabled */
|
/* FIXME: should have a benchmark fallback for the case where orc is disabled */
|
||||||
#if defined(AUDIORESAMPLE_FORMAT_AUTO) && !defined(DISABLE_ORC)
|
#if defined(AUDIORESAMPLE_FORMAT_AUTO) && !defined(DISABLE_ORC)
|
||||||
|
|
||||||
|
@ -1367,13 +1463,19 @@ _benchmark_integer_resampling (void)
|
||||||
orc_profile_init (&a);
|
orc_profile_init (&a);
|
||||||
orc_profile_init (&b);
|
orc_profile_init (&b);
|
||||||
|
|
||||||
sta = resample_float_resampler_init (1, 48000, 24000, 4, NULL);
|
sta = resample_float_resampler_init (1, 48000, 24000, 4,
|
||||||
|
SPEEX_RESAMPLER_SINC_FILTER_INTERPOLATED,
|
||||||
|
SPEEX_RESAMPLER_SINC_FILTER_AUTO_THRESHOLD_DEFAULT,
|
||||||
|
NULL);
|
||||||
if (sta == NULL) {
|
if (sta == NULL) {
|
||||||
GST_ERROR ("Failed to create float resampler state");
|
GST_ERROR ("Failed to create float resampler state");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
stb = resample_int_resampler_init (1, 48000, 24000, 4, NULL);
|
stb = resample_int_resampler_init (1, 48000, 24000, 4,
|
||||||
|
SPEEX_RESAMPLER_SINC_FILTER_INTERPOLATED,
|
||||||
|
SPEEX_RESAMPLER_SINC_FILTER_AUTO_THRESHOLD_DEFAULT,
|
||||||
|
NULL);
|
||||||
if (stb == NULL) {
|
if (stb == NULL) {
|
||||||
resample_float_resampler_destroy (sta);
|
resample_float_resampler_destroy (sta);
|
||||||
GST_ERROR ("Failed to create int resampler state");
|
GST_ERROR ("Failed to create int resampler state");
|
||||||
|
|
|
@ -77,6 +77,9 @@ struct _GstAudioResample {
|
||||||
gint inrate;
|
gint inrate;
|
||||||
gint outrate;
|
gint outrate;
|
||||||
|
|
||||||
|
SpeexResamplerSincFilterMode sinc_filter_mode;
|
||||||
|
guint32 sinc_filter_auto_threshold;
|
||||||
|
|
||||||
guint8 *tmp_in;
|
guint8 *tmp_in;
|
||||||
guint tmp_in_size;
|
guint tmp_in_size;
|
||||||
|
|
||||||
|
|
|
@ -184,6 +184,7 @@ struct SpeexResamplerState_
|
||||||
spx_uint32_t oversample;
|
spx_uint32_t oversample;
|
||||||
int initialised;
|
int initialised;
|
||||||
int started;
|
int started;
|
||||||
|
int use_full_sinc_table;
|
||||||
|
|
||||||
/* These are per-channel */
|
/* These are per-channel */
|
||||||
spx_int32_t *last_sample;
|
spx_int32_t *last_sample;
|
||||||
|
@ -754,7 +755,8 @@ update_filter (SpeexResamplerState * st)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Choose the resampling type that requires the least amount of memory */
|
/* Choose the resampling type that requires the least amount of memory */
|
||||||
if (st->den_rate <= st->oversample) {
|
/* Or if the full sinc table is explicitely requested, use that */
|
||||||
|
if (st->use_full_sinc_table || (st->den_rate <= st->oversample)) {
|
||||||
spx_uint32_t i;
|
spx_uint32_t i;
|
||||||
if (!st->sinc_table)
|
if (!st->sinc_table)
|
||||||
st->sinc_table =
|
st->sinc_table =
|
||||||
|
@ -918,10 +920,11 @@ update_filter (SpeexResamplerState * st)
|
||||||
|
|
||||||
EXPORT SpeexResamplerState *
|
EXPORT SpeexResamplerState *
|
||||||
speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate,
|
speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate,
|
||||||
spx_uint32_t out_rate, int quality, int *err)
|
spx_uint32_t out_rate, int quality, SpeexResamplerSincFilterMode sinc_filter_mode,
|
||||||
|
spx_uint32_t sinc_filter_auto_threshold, int *err)
|
||||||
{
|
{
|
||||||
return speex_resampler_init_frac (nb_channels, in_rate, out_rate, in_rate,
|
return speex_resampler_init_frac (nb_channels, in_rate, out_rate, in_rate,
|
||||||
out_rate, quality, err);
|
out_rate, quality, sinc_filter_mode, sinc_filter_auto_threshold, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined HAVE_ORC && !defined DISABLE_ORC
|
#if defined HAVE_ORC && !defined DISABLE_ORC
|
||||||
|
@ -940,15 +943,33 @@ check_insn_set (SpeexResamplerState * st, const char *name)
|
||||||
EXPORT SpeexResamplerState *
|
EXPORT SpeexResamplerState *
|
||||||
speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num,
|
speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num,
|
||||||
spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate,
|
spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate,
|
||||||
int quality, int *err)
|
int quality, SpeexResamplerSincFilterMode sinc_filter_mode,
|
||||||
|
spx_uint32_t sinc_filter_auto_threshold, int *err)
|
||||||
{
|
{
|
||||||
spx_uint32_t i;
|
spx_uint32_t i;
|
||||||
SpeexResamplerState *st;
|
SpeexResamplerState *st;
|
||||||
|
int use_full_sinc_table = 0;
|
||||||
if (quality > 10 || quality < 0) {
|
if (quality > 10 || quality < 0) {
|
||||||
if (err)
|
if (err)
|
||||||
*err = RESAMPLER_ERR_INVALID_ARG;
|
*err = RESAMPLER_ERR_INVALID_ARG;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
switch (sinc_filter_mode) {
|
||||||
|
case RESAMPLER_SINC_FILTER_INTERPOLATED:
|
||||||
|
use_full_sinc_table = 0;
|
||||||
|
break;
|
||||||
|
case RESAMPLER_SINC_FILTER_FULL:
|
||||||
|
use_full_sinc_table = 1;
|
||||||
|
break;
|
||||||
|
case RESAMPLER_SINC_FILTER_AUTO:
|
||||||
|
/* Handled below */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (err)
|
||||||
|
*err = RESAMPLER_ERR_INVALID_ARG;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
st = (SpeexResamplerState *) speex_alloc (sizeof (SpeexResamplerState));
|
st = (SpeexResamplerState *) speex_alloc (sizeof (SpeexResamplerState));
|
||||||
st->initialised = 0;
|
st->initialised = 0;
|
||||||
st->started = 0;
|
st->started = 0;
|
||||||
|
@ -962,6 +983,7 @@ speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num,
|
||||||
st->filt_len = 0;
|
st->filt_len = 0;
|
||||||
st->mem = 0;
|
st->mem = 0;
|
||||||
st->resampler_ptr = 0;
|
st->resampler_ptr = 0;
|
||||||
|
st->use_full_sinc_table = use_full_sinc_table;
|
||||||
|
|
||||||
st->cutoff = 1.f;
|
st->cutoff = 1.f;
|
||||||
st->nb_channels = nb_channels;
|
st->nb_channels = nb_channels;
|
||||||
|
@ -1004,6 +1026,16 @@ speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num,
|
||||||
speex_resampler_set_quality (st, quality);
|
speex_resampler_set_quality (st, quality);
|
||||||
speex_resampler_set_rate_frac (st, ratio_num, ratio_den, in_rate, out_rate);
|
speex_resampler_set_rate_frac (st, ratio_num, ratio_den, in_rate, out_rate);
|
||||||
|
|
||||||
|
if (sinc_filter_mode == RESAMPLER_SINC_FILTER_AUTO) {
|
||||||
|
/*
|
||||||
|
Estimate how big the filter table would become if the full mode were to be used
|
||||||
|
calculations used correspond to the ones in update_filter()
|
||||||
|
if the size is bigger than the threshold, use interpolated sinc instead
|
||||||
|
*/
|
||||||
|
spx_uint32_t base_filter_length = st->filt_len = quality_map[st->quality].base_length;
|
||||||
|
spx_uint32_t filter_table_size = base_filter_length * st->den_rate * sizeof(spx_uint16_t);
|
||||||
|
st->use_full_sinc_table = (filter_table_size > sinc_filter_auto_threshold) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
update_filter (st);
|
update_filter (st);
|
||||||
|
|
||||||
|
@ -1391,6 +1423,12 @@ speex_resampler_get_filt_len (SpeexResamplerState * st)
|
||||||
return st->filt_len;
|
return st->filt_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT int
|
||||||
|
speex_resampler_get_sinc_filter_mode (SpeexResamplerState * st)
|
||||||
|
{
|
||||||
|
return st->use_full_sinc_table;
|
||||||
|
}
|
||||||
|
|
||||||
EXPORT int
|
EXPORT int
|
||||||
speex_resampler_skip_zeros (SpeexResamplerState * st)
|
speex_resampler_skip_zeros (SpeexResamplerState * st)
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
#define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency)
|
#define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency)
|
||||||
#define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency)
|
#define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency)
|
||||||
#define speex_resampler_get_filt_len CAT_PREFIX(RANDOM_PREFIX,_resampler_get_filt_len)
|
#define speex_resampler_get_filt_len CAT_PREFIX(RANDOM_PREFIX,_resampler_get_filt_len)
|
||||||
|
#define speex_resampler_get_sinc_filter_mode CAT_PREFIX(RANDOM_PREFIX,_resampler_get_sinc_filter_mode)
|
||||||
#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros)
|
#define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros)
|
||||||
#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
|
#define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
|
||||||
#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
|
#define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
|
||||||
|
@ -113,6 +114,15 @@ enum {
|
||||||
RESAMPLER_ERR_MAX_ERROR
|
RESAMPLER_ERR_MAX_ERROR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RESAMPLER_SINC_FILTER_INTERPOLATED = 0,
|
||||||
|
RESAMPLER_SINC_FILTER_FULL = 1,
|
||||||
|
RESAMPLER_SINC_FILTER_AUTO = 2
|
||||||
|
} SpeexResamplerSincFilterMode;
|
||||||
|
|
||||||
|
#define RESAMPLER_SINC_FILTER_DEFAULT RESAMPLER_SINC_FILTER_INTERPOLATED
|
||||||
|
#define RESAMPLER_SINC_FILTER_AUTO_THRESHOLD_DEFAULT (1 * 1048576)
|
||||||
|
|
||||||
struct SpeexResamplerState_;
|
struct SpeexResamplerState_;
|
||||||
typedef struct SpeexResamplerState_ SpeexResamplerState;
|
typedef struct SpeexResamplerState_ SpeexResamplerState;
|
||||||
|
|
||||||
|
@ -122,13 +132,23 @@ typedef struct SpeexResamplerState_ SpeexResamplerState;
|
||||||
* @param out_rate Output sampling rate (integer number of Hz).
|
* @param out_rate Output sampling rate (integer number of Hz).
|
||||||
* @param quality Resampling quality between 0 and 10, where 0 has poor quality
|
* @param quality Resampling quality between 0 and 10, where 0 has poor quality
|
||||||
* and 10 has very high quality.
|
* and 10 has very high quality.
|
||||||
|
* @param sinc_filter_mode Sinc filter table mode to use
|
||||||
|
* @param sinc_filter_auto_threshold Threshold to use if sinc filter mode is auto, in bytes
|
||||||
* @return Newly created resampler state
|
* @return Newly created resampler state
|
||||||
* @retval NULL Error: not enough memory
|
* @retval NULL Error: not enough memory
|
||||||
|
*
|
||||||
|
* If a full filter table would be larger than the auto threshold, and sinc_filter_mode is AUTO,
|
||||||
|
* the resample uses the interpolated mode instead
|
||||||
|
*
|
||||||
|
* @note A full sinc table can significantly improve the resampler's performance, but calculating the table
|
||||||
|
* takes longer, as opposed to the interpolated variant
|
||||||
*/
|
*/
|
||||||
SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels,
|
SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels,
|
||||||
spx_uint32_t in_rate,
|
spx_uint32_t in_rate,
|
||||||
spx_uint32_t out_rate,
|
spx_uint32_t out_rate,
|
||||||
int quality,
|
int quality,
|
||||||
|
SpeexResamplerSincFilterMode sinc_filter_mode,
|
||||||
|
spx_uint32_t sinc_filter_auto_threshold,
|
||||||
int *err);
|
int *err);
|
||||||
|
|
||||||
/** Create a new resampler with fractional input/output rates. The sampling
|
/** Create a new resampler with fractional input/output rates. The sampling
|
||||||
|
@ -141,8 +161,16 @@ SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels,
|
||||||
* @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
|
* @param out_rate Output sampling rate rounded to the nearest integer (in Hz).
|
||||||
* @param quality Resampling quality between 0 and 10, where 0 has poor quality
|
* @param quality Resampling quality between 0 and 10, where 0 has poor quality
|
||||||
* and 10 has very high quality.
|
* and 10 has very high quality.
|
||||||
|
* @param sinc_filter_mode Sinc filter table mode to use
|
||||||
|
* @param sinc_filter_auto_threshold Threshold to use if sinc filter mode is auto, in bytes
|
||||||
* @return Newly created resampler state
|
* @return Newly created resampler state
|
||||||
* @retval NULL Error: not enough memory
|
* @retval NULL Error: not enough memory
|
||||||
|
*
|
||||||
|
* If a full filter table would be larger than the auto threshold, and sinc_filter_mode is AUTO,
|
||||||
|
* the resample uses the interpolated mode instead
|
||||||
|
*
|
||||||
|
* @note A full sinc table can significantly improve the resampler's performance, but calculating the table
|
||||||
|
* takes longer, as opposed to the interpolated variant
|
||||||
*/
|
*/
|
||||||
SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
|
SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
|
||||||
spx_uint32_t ratio_num,
|
spx_uint32_t ratio_num,
|
||||||
|
@ -150,6 +178,8 @@ SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels,
|
||||||
spx_uint32_t in_rate,
|
spx_uint32_t in_rate,
|
||||||
spx_uint32_t out_rate,
|
spx_uint32_t out_rate,
|
||||||
int quality,
|
int quality,
|
||||||
|
SpeexResamplerSincFilterMode sinc_filter_mode,
|
||||||
|
spx_uint32_t sinc_filter_auto_threshold,
|
||||||
int *err);
|
int *err);
|
||||||
|
|
||||||
/** Destroy a resampler state.
|
/** Destroy a resampler state.
|
||||||
|
@ -339,6 +369,12 @@ int speex_resampler_get_output_latency(SpeexResamplerState *st);
|
||||||
*/
|
*/
|
||||||
int speex_resampler_get_filt_len(SpeexResamplerState *st);
|
int speex_resampler_get_filt_len(SpeexResamplerState *st);
|
||||||
|
|
||||||
|
/** Returns 1 if the full sinc filter table is used, 0 if the interpolated one is used
|
||||||
|
* @param st Resampler state
|
||||||
|
* @return Sinc filter mode
|
||||||
|
*/
|
||||||
|
int speex_resampler_get_sinc_filter_mode(SpeexResamplerState *st);
|
||||||
|
|
||||||
/** Make sure that the first samples to go out of the resamplers don't have
|
/** Make sure that the first samples to go out of the resamplers don't have
|
||||||
* leading zeros. This is only useful before starting to use a newly created
|
* leading zeros. This is only useful before starting to use a newly created
|
||||||
* resampler. It is recommended to use that when resampling an audio file, as
|
* resampler. It is recommended to use that when resampling an audio file, as
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#define SPEEX_RESAMPLER_QUALITY_VOIP 3
|
#define SPEEX_RESAMPLER_QUALITY_VOIP 3
|
||||||
#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
|
#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5
|
||||||
|
|
||||||
|
#define SPEEX_RESAMPLER_SINC_FILTER_DEFAULT SPEEX_RESAMPLER_SINC_FILTER_INTERPOLATED
|
||||||
|
#define SPEEX_RESAMPLER_SINC_FILTER_AUTO_THRESHOLD_DEFAULT (1 * 1048576)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
RESAMPLER_ERR_SUCCESS = 0,
|
RESAMPLER_ERR_SUCCESS = 0,
|
||||||
|
@ -37,11 +40,19 @@ enum
|
||||||
RESAMPLER_ERR_MAX_ERROR
|
RESAMPLER_ERR_MAX_ERROR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SPEEX_RESAMPLER_SINC_FILTER_INTERPOLATED = 0,
|
||||||
|
SPEEX_RESAMPLER_SINC_FILTER_FULL = 1,
|
||||||
|
SPEEX_RESAMPLER_SINC_FILTER_AUTO = 2
|
||||||
|
} SpeexResamplerSincFilterMode;
|
||||||
|
|
||||||
typedef struct SpeexResamplerState_ SpeexResamplerState;
|
typedef struct SpeexResamplerState_ SpeexResamplerState;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SpeexResamplerState *(*init) (guint32 nb_channels,
|
SpeexResamplerState *(*init) (guint32 nb_channels,
|
||||||
guint32 in_rate, guint32 out_rate, gint quality, gint * err);
|
guint32 in_rate, guint32 out_rate, gint quality,
|
||||||
|
SpeexResamplerSincFilterMode sinc_filter_mode,
|
||||||
|
guint32 sinc_filter_auto_threshold, gint * err);
|
||||||
void (*destroy) (SpeexResamplerState * st);
|
void (*destroy) (SpeexResamplerState * st);
|
||||||
int (*process) (SpeexResamplerState *
|
int (*process) (SpeexResamplerState *
|
||||||
st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
|
st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
|
||||||
|
@ -53,6 +64,7 @@ typedef struct {
|
||||||
guint32 * ratio_num, guint32 * ratio_den);
|
guint32 * ratio_num, guint32 * ratio_den);
|
||||||
int (*get_input_latency) (SpeexResamplerState * st);
|
int (*get_input_latency) (SpeexResamplerState * st);
|
||||||
int (*get_filt_len) (SpeexResamplerState * st);
|
int (*get_filt_len) (SpeexResamplerState * st);
|
||||||
|
int (*get_sinc_filter_mode) (SpeexResamplerState * st);
|
||||||
int (*set_quality) (SpeexResamplerState * st, gint quality);
|
int (*set_quality) (SpeexResamplerState * st, gint quality);
|
||||||
int (*reset_mem) (SpeexResamplerState * st);
|
int (*reset_mem) (SpeexResamplerState * st);
|
||||||
int (*skip_zeros) (SpeexResamplerState * st);
|
int (*skip_zeros) (SpeexResamplerState * st);
|
||||||
|
@ -61,7 +73,9 @@ typedef struct {
|
||||||
} SpeexResampleFuncs;
|
} SpeexResampleFuncs;
|
||||||
|
|
||||||
SpeexResamplerState *resample_float_resampler_init (guint32 nb_channels,
|
SpeexResamplerState *resample_float_resampler_init (guint32 nb_channels,
|
||||||
guint32 in_rate, guint32 out_rate, gint quality, gint * err);
|
guint32 in_rate, guint32 out_rate, gint quality,
|
||||||
|
SpeexResamplerSincFilterMode sinc_filter_mode,
|
||||||
|
guint32 sinc_filter_auto_threshold, gint * err);
|
||||||
void resample_float_resampler_destroy (SpeexResamplerState * st);
|
void resample_float_resampler_destroy (SpeexResamplerState * st);
|
||||||
int resample_float_resampler_process_interleaved_float (SpeexResamplerState *
|
int resample_float_resampler_process_interleaved_float (SpeexResamplerState *
|
||||||
st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
|
st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
|
||||||
|
@ -73,6 +87,7 @@ void resample_float_resampler_get_ratio (SpeexResamplerState * st,
|
||||||
guint32 * ratio_num, guint32 * ratio_den);
|
guint32 * ratio_num, guint32 * ratio_den);
|
||||||
int resample_float_resampler_get_input_latency (SpeexResamplerState * st);
|
int resample_float_resampler_get_input_latency (SpeexResamplerState * st);
|
||||||
int resample_float_resampler_get_filt_len (SpeexResamplerState * st);
|
int resample_float_resampler_get_filt_len (SpeexResamplerState * st);
|
||||||
|
int resample_float_resampler_get_sinc_filter_mode (SpeexResamplerState * st);
|
||||||
int resample_float_resampler_set_quality (SpeexResamplerState * st, gint quality);
|
int resample_float_resampler_set_quality (SpeexResamplerState * st, gint quality);
|
||||||
int resample_float_resampler_reset_mem (SpeexResamplerState * st);
|
int resample_float_resampler_reset_mem (SpeexResamplerState * st);
|
||||||
int resample_float_resampler_skip_zeros (SpeexResamplerState * st);
|
int resample_float_resampler_skip_zeros (SpeexResamplerState * st);
|
||||||
|
@ -88,6 +103,7 @@ static const SpeexResampleFuncs float_funcs =
|
||||||
resample_float_resampler_get_ratio,
|
resample_float_resampler_get_ratio,
|
||||||
resample_float_resampler_get_input_latency,
|
resample_float_resampler_get_input_latency,
|
||||||
resample_float_resampler_get_filt_len,
|
resample_float_resampler_get_filt_len,
|
||||||
|
resample_float_resampler_get_sinc_filter_mode,
|
||||||
resample_float_resampler_set_quality,
|
resample_float_resampler_set_quality,
|
||||||
resample_float_resampler_reset_mem,
|
resample_float_resampler_reset_mem,
|
||||||
resample_float_resampler_skip_zeros,
|
resample_float_resampler_skip_zeros,
|
||||||
|
@ -96,7 +112,9 @@ static const SpeexResampleFuncs float_funcs =
|
||||||
};
|
};
|
||||||
|
|
||||||
SpeexResamplerState *resample_double_resampler_init (guint32 nb_channels,
|
SpeexResamplerState *resample_double_resampler_init (guint32 nb_channels,
|
||||||
guint32 in_rate, guint32 out_rate, gint quality, gint * err);
|
guint32 in_rate, guint32 out_rate, gint quality,
|
||||||
|
SpeexResamplerSincFilterMode sinc_filter_mode,
|
||||||
|
guint32 sinc_filter_auto_threshold, gint * err);
|
||||||
void resample_double_resampler_destroy (SpeexResamplerState * st);
|
void resample_double_resampler_destroy (SpeexResamplerState * st);
|
||||||
int resample_double_resampler_process_interleaved_float (SpeexResamplerState *
|
int resample_double_resampler_process_interleaved_float (SpeexResamplerState *
|
||||||
st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
|
st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
|
||||||
|
@ -108,6 +126,7 @@ void resample_double_resampler_get_ratio (SpeexResamplerState * st,
|
||||||
guint32 * ratio_num, guint32 * ratio_den);
|
guint32 * ratio_num, guint32 * ratio_den);
|
||||||
int resample_double_resampler_get_input_latency (SpeexResamplerState * st);
|
int resample_double_resampler_get_input_latency (SpeexResamplerState * st);
|
||||||
int resample_double_resampler_get_filt_len (SpeexResamplerState * st);
|
int resample_double_resampler_get_filt_len (SpeexResamplerState * st);
|
||||||
|
int resample_double_resampler_get_sinc_filter_mode (SpeexResamplerState * st);
|
||||||
int resample_double_resampler_set_quality (SpeexResamplerState * st, gint quality);
|
int resample_double_resampler_set_quality (SpeexResamplerState * st, gint quality);
|
||||||
int resample_double_resampler_reset_mem (SpeexResamplerState * st);
|
int resample_double_resampler_reset_mem (SpeexResamplerState * st);
|
||||||
int resample_double_resampler_skip_zeros (SpeexResamplerState * st);
|
int resample_double_resampler_skip_zeros (SpeexResamplerState * st);
|
||||||
|
@ -123,6 +142,7 @@ static const SpeexResampleFuncs double_funcs =
|
||||||
resample_double_resampler_get_ratio,
|
resample_double_resampler_get_ratio,
|
||||||
resample_double_resampler_get_input_latency,
|
resample_double_resampler_get_input_latency,
|
||||||
resample_double_resampler_get_filt_len,
|
resample_double_resampler_get_filt_len,
|
||||||
|
resample_double_resampler_get_sinc_filter_mode,
|
||||||
resample_double_resampler_set_quality,
|
resample_double_resampler_set_quality,
|
||||||
resample_double_resampler_reset_mem,
|
resample_double_resampler_reset_mem,
|
||||||
resample_double_resampler_skip_zeros,
|
resample_double_resampler_skip_zeros,
|
||||||
|
@ -131,7 +151,9 @@ static const SpeexResampleFuncs double_funcs =
|
||||||
};
|
};
|
||||||
|
|
||||||
SpeexResamplerState *resample_int_resampler_init (guint32 nb_channels,
|
SpeexResamplerState *resample_int_resampler_init (guint32 nb_channels,
|
||||||
guint32 in_rate, guint32 out_rate, gint quality, gint * err);
|
guint32 in_rate, guint32 out_rate, gint quality,
|
||||||
|
SpeexResamplerSincFilterMode sinc_filter_mode,
|
||||||
|
guint32 sinc_filter_auto_threshold, gint * err);
|
||||||
void resample_int_resampler_destroy (SpeexResamplerState * st);
|
void resample_int_resampler_destroy (SpeexResamplerState * st);
|
||||||
int resample_int_resampler_process_interleaved_int (SpeexResamplerState *
|
int resample_int_resampler_process_interleaved_int (SpeexResamplerState *
|
||||||
st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
|
st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
|
||||||
|
@ -143,6 +165,7 @@ void resample_int_resampler_get_ratio (SpeexResamplerState * st,
|
||||||
guint32 * ratio_num, guint32 * ratio_den);
|
guint32 * ratio_num, guint32 * ratio_den);
|
||||||
int resample_int_resampler_get_input_latency (SpeexResamplerState * st);
|
int resample_int_resampler_get_input_latency (SpeexResamplerState * st);
|
||||||
int resample_int_resampler_get_filt_len (SpeexResamplerState * st);
|
int resample_int_resampler_get_filt_len (SpeexResamplerState * st);
|
||||||
|
int resample_int_resampler_get_sinc_filter_mode (SpeexResamplerState * st);
|
||||||
int resample_int_resampler_set_quality (SpeexResamplerState * st, gint quality);
|
int resample_int_resampler_set_quality (SpeexResamplerState * st, gint quality);
|
||||||
int resample_int_resampler_reset_mem (SpeexResamplerState * st);
|
int resample_int_resampler_reset_mem (SpeexResamplerState * st);
|
||||||
int resample_int_resampler_skip_zeros (SpeexResamplerState * st);
|
int resample_int_resampler_skip_zeros (SpeexResamplerState * st);
|
||||||
|
@ -158,6 +181,7 @@ static const SpeexResampleFuncs int_funcs =
|
||||||
resample_int_resampler_get_ratio,
|
resample_int_resampler_get_ratio,
|
||||||
resample_int_resampler_get_input_latency,
|
resample_int_resampler_get_input_latency,
|
||||||
resample_int_resampler_get_filt_len,
|
resample_int_resampler_get_filt_len,
|
||||||
|
resample_int_resampler_get_sinc_filter_mode,
|
||||||
resample_int_resampler_set_quality,
|
resample_int_resampler_set_quality,
|
||||||
resample_int_resampler_reset_mem,
|
resample_int_resampler_reset_mem,
|
||||||
resample_int_resampler_skip_zeros,
|
resample_int_resampler_skip_zeros,
|
||||||
|
|
Loading…
Reference in a new issue