From: Carlos Rafael Giani Date: Sun, 7 Oct 2012 01:00:52 +0000 (+0200) Subject: audioresample: sinc filter performance improvements X-Git-Tag: 1.19.3~511^2~5805 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c41faa3d8ea549479d61472b034a8f26fabe355c;hp=d8b42ae80c040c578973aeb460dc4d9b3ac6a5ed;p=platform%2Fupstream%2Fgstreamer.git 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 --- diff --git a/gst/audioresample/gstaudioresample.c b/gst/audioresample/gstaudioresample.c index fa73ec1..0a1bdb0 100644 --- a/gst/audioresample/gstaudioresample.c +++ b/gst/audioresample/gstaudioresample.c @@ -25,6 +25,14 @@ * audioresample resamples raw audio buffers to different sample rates using * 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. + * * * Example launch line * |[ @@ -62,10 +70,14 @@ GST_DEBUG_CATEGORY (audio_resample_debug); GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE); #endif +#define GST_TYPE_SPEEX_RESAMPLER_SINC_FILTER_MODE (speex_resampler_sinc_filter_mode_get_type ()) + enum { PROP_0, - PROP_QUALITY + PROP_QUALITY, + PROP_SINC_FILTER_MODE, + PROP_SINC_FILTER_AUTO_THRESHOLD }; #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, guint prop_id, GValue * value, GParamSpec * pspec); +static GType +speex_resampler_sinc_filter_mode_get_type (void); + /* vmethods */ static gboolean gst_audio_resample_get_unit_size (GstBaseTransform * base, GstCaps * caps, gsize * size); @@ -144,6 +159,20 @@ gst_audio_resample_class_init (GstAudioResampleClass * klass) SPEEX_RESAMPLER_QUALITY_DEFAULT, 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_static_pad_template_get (&gst_audio_resample_src_template)); gst_element_class_add_pad_template (gstelement_class, @@ -181,6 +210,8 @@ gst_audio_resample_init (GstAudioResample * resample) GstBaseTransform *trans = GST_BASE_TRANSFORM (resample); 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_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 * 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; gint err = RESAMPLER_ERR_SUCCESS; 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)) { 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; } + 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); return ret; @@ -370,7 +409,9 @@ gst_audio_resample_init_state (GstAudioResample * resample, gint width, static gboolean 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 updated_latency = FALSE; @@ -381,11 +422,12 @@ gst_audio_resample_update_state (GstAudioResample * resample, gint width, if (resample->state == NULL) { ret = TRUE; } 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->state = 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); ret = (resample->state != NULL); @@ -417,6 +459,8 @@ gst_audio_resample_update_state (GstAudioResample * resample, gint width, resample->quality = quality; resample->inrate = inrate; resample->outrate = outrate; + resample->sinc_filter_mode = sinc_filter_mode; + resample->sinc_filter_auto_threshold = sinc_filter_auto_threshold; if (updated_latency) gst_element_post_message (GST_ELEMENT (resample), @@ -526,7 +570,8 @@ gst_audio_resample_set_caps (GstBaseTransform * base, GstCaps * incaps, ret = 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)) return FALSE; @@ -1126,7 +1171,8 @@ gst_audio_resample_transform (GstBaseTransform * base, GstBuffer * inbuf, if (G_UNLIKELY (!(resample->state = gst_audio_resample_init_state (resample, resample->width, 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; resample->funcs = @@ -1279,8 +1325,31 @@ gst_audio_resample_set_property (GObject * object, guint prop_id, gst_audio_resample_update_state (resample, resample->width, resample->channels, resample->inrate, resample->outrate, - quality, resample->fp); + quality, resample->fp, resample->sinc_filter_mode, + resample->sinc_filter_auto_threshold); + 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: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1299,12 +1368,39 @@ gst_audio_resample_get_property (GObject * object, guint prop_id, case PROP_QUALITY: g_value_set_int (value, resample->quality); 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: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 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 */ #if defined(AUDIORESAMPLE_FORMAT_AUTO) && !defined(DISABLE_ORC) @@ -1367,13 +1463,19 @@ _benchmark_integer_resampling (void) orc_profile_init (&a); 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) { GST_ERROR ("Failed to create float resampler state"); 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) { resample_float_resampler_destroy (sta); GST_ERROR ("Failed to create int resampler state"); diff --git a/gst/audioresample/gstaudioresample.h b/gst/audioresample/gstaudioresample.h index da75b64..df2d2f1 100644 --- a/gst/audioresample/gstaudioresample.h +++ b/gst/audioresample/gstaudioresample.h @@ -77,6 +77,9 @@ struct _GstAudioResample { gint inrate; gint outrate; + SpeexResamplerSincFilterMode sinc_filter_mode; + guint32 sinc_filter_auto_threshold; + guint8 *tmp_in; guint tmp_in_size; diff --git a/gst/audioresample/resample.c b/gst/audioresample/resample.c index fefa0c5..bd36bfa 100644 --- a/gst/audioresample/resample.c +++ b/gst/audioresample/resample.c @@ -184,6 +184,7 @@ struct SpeexResamplerState_ spx_uint32_t oversample; int initialised; int started; + int use_full_sinc_table; /* These are per-channel */ spx_int32_t *last_sample; @@ -754,7 +755,8 @@ update_filter (SpeexResamplerState * st) } /* 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; if (!st->sinc_table) st->sinc_table = @@ -918,10 +920,11 @@ update_filter (SpeexResamplerState * st) EXPORT SpeexResamplerState * 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, - out_rate, quality, err); + out_rate, quality, sinc_filter_mode, sinc_filter_auto_threshold, err); } #if defined HAVE_ORC && !defined DISABLE_ORC @@ -940,15 +943,33 @@ check_insn_set (SpeexResamplerState * st, const char *name) EXPORT SpeexResamplerState * 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, - int quality, int *err) + int quality, SpeexResamplerSincFilterMode sinc_filter_mode, + spx_uint32_t sinc_filter_auto_threshold, int *err) { spx_uint32_t i; SpeexResamplerState *st; + int use_full_sinc_table = 0; if (quality > 10 || quality < 0) { if (err) *err = RESAMPLER_ERR_INVALID_ARG; 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->initialised = 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->mem = 0; st->resampler_ptr = 0; + st->use_full_sinc_table = use_full_sinc_table; st->cutoff = 1.f; 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_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); @@ -1392,6 +1424,12 @@ speex_resampler_get_filt_len (SpeexResamplerState * st) } EXPORT int +speex_resampler_get_sinc_filter_mode (SpeexResamplerState * st) +{ + return st->use_full_sinc_table; +} + +EXPORT int speex_resampler_skip_zeros (SpeexResamplerState * st) { spx_uint32_t i; diff --git a/gst/audioresample/speex_resampler.h b/gst/audioresample/speex_resampler.h index 894b380..b9aaa2c 100644 --- a/gst/audioresample/speex_resampler.h +++ b/gst/audioresample/speex_resampler.h @@ -74,6 +74,7 @@ #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_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_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem) #define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror) @@ -113,6 +114,15 @@ enum { 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_; typedef struct SpeexResamplerState_ SpeexResamplerState; @@ -122,13 +132,23 @@ typedef struct SpeexResamplerState_ SpeexResamplerState; * @param out_rate Output sampling rate (integer number of Hz). * @param quality Resampling quality between 0 and 10, where 0 has poor 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 * @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, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, + SpeexResamplerSincFilterMode sinc_filter_mode, + spx_uint32_t sinc_filter_auto_threshold, int *err); /** 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 quality Resampling quality between 0 and 10, where 0 has poor 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 * @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, 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 out_rate, int quality, + SpeexResamplerSincFilterMode sinc_filter_mode, + spx_uint32_t sinc_filter_auto_threshold, int *err); /** Destroy a resampler state. @@ -339,6 +369,12 @@ int speex_resampler_get_output_latency(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 * 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 diff --git a/gst/audioresample/speex_resampler_wrapper.h b/gst/audioresample/speex_resampler_wrapper.h index 08a82bc..5a13dee 100644 --- a/gst/audioresample/speex_resampler_wrapper.h +++ b/gst/audioresample/speex_resampler_wrapper.h @@ -26,6 +26,9 @@ #define SPEEX_RESAMPLER_QUALITY_VOIP 3 #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 { RESAMPLER_ERR_SUCCESS = 0, @@ -37,11 +40,19 @@ enum 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 *(*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); int (*process) (SpeexResamplerState * st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len); @@ -53,6 +64,7 @@ typedef struct { guint32 * ratio_num, guint32 * ratio_den); int (*get_input_latency) (SpeexResamplerState * st); int (*get_filt_len) (SpeexResamplerState * st); + int (*get_sinc_filter_mode) (SpeexResamplerState * st); int (*set_quality) (SpeexResamplerState * st, gint quality); int (*reset_mem) (SpeexResamplerState * st); int (*skip_zeros) (SpeexResamplerState * st); @@ -61,7 +73,9 @@ typedef struct { } SpeexResampleFuncs; 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); int resample_float_resampler_process_interleaved_float (SpeexResamplerState * 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); int resample_float_resampler_get_input_latency (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_reset_mem (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_input_latency, resample_float_resampler_get_filt_len, + resample_float_resampler_get_sinc_filter_mode, resample_float_resampler_set_quality, resample_float_resampler_reset_mem, resample_float_resampler_skip_zeros, @@ -96,7 +112,9 @@ static const SpeexResampleFuncs float_funcs = }; 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); int resample_double_resampler_process_interleaved_float (SpeexResamplerState * 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); int resample_double_resampler_get_input_latency (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_reset_mem (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_input_latency, resample_double_resampler_get_filt_len, + resample_double_resampler_get_sinc_filter_mode, resample_double_resampler_set_quality, resample_double_resampler_reset_mem, resample_double_resampler_skip_zeros, @@ -131,7 +151,9 @@ static const SpeexResampleFuncs double_funcs = }; 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); int resample_int_resampler_process_interleaved_int (SpeexResamplerState * 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); int resample_int_resampler_get_input_latency (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_reset_mem (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_input_latency, resample_int_resampler_get_filt_len, + resample_int_resampler_get_sinc_filter_mode, resample_int_resampler_set_quality, resample_int_resampler_reset_mem, resample_int_resampler_skip_zeros,