mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-22 23:28:16 +00:00
audio-resampler: improve filter construction
Remove some unused variables from the inner product functions. Make filter coefficients by interpolating if required. Rename some fields. Try hard to not recalculate filters when just chaging the rate. Add more proprties to audioresample.
This commit is contained in:
parent
0f3ff9177f
commit
524ea147cc
5 changed files with 533 additions and 294 deletions
|
@ -337,15 +337,14 @@ gst_audio_converter_update_config (GstAudioConverter * convert,
|
|||
convert->in.rate = in_rate;
|
||||
convert->out.rate = out_rate;
|
||||
|
||||
if (convert->resampler)
|
||||
gst_audio_resampler_update (convert->resampler, in_rate, out_rate, config);
|
||||
|
||||
if (config) {
|
||||
gst_structure_foreach (config, copy_config, convert);
|
||||
gst_structure_free (config);
|
||||
}
|
||||
|
||||
if (convert->resampler)
|
||||
gst_audio_resampler_update (convert->resampler, in_rate, out_rate,
|
||||
convert->config);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
static inline void
|
||||
inner_product_gfloat_none_1_sse (gfloat * o, const gfloat * a,
|
||||
const gfloat * b, gint len, const gfloat * icoeff, gint oversample)
|
||||
const gfloat * b, gint len, const gfloat * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128 sum = _mm_setzero_ps ();
|
||||
|
@ -42,12 +42,13 @@ inner_product_gfloat_none_1_sse (gfloat * o, const gfloat * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gfloat_linear_1_sse (gfloat * o, const gfloat * a,
|
||||
const gfloat * b, gint len, const gfloat * icoeff, gint oversample)
|
||||
const gfloat * b, gint len, const gfloat * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128 sum = _mm_setzero_ps (), t;
|
||||
__m128 sum, t;
|
||||
__m128 f = _mm_loadu_ps(icoeff);
|
||||
|
||||
sum = _mm_setzero_ps ();
|
||||
for (; i < len; i += 4) {
|
||||
t = _mm_loadu_ps (a + i);
|
||||
sum = _mm_add_ps (sum, _mm_mul_ps (_mm_unpacklo_ps (t, t),
|
||||
|
@ -63,7 +64,7 @@ inner_product_gfloat_linear_1_sse (gfloat * o, const gfloat * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gfloat_cubic_1_sse (gfloat * o, const gfloat * a,
|
||||
const gfloat * b, gint len, const gfloat * icoeff, gint oversample)
|
||||
const gfloat * b, gint len, const gfloat * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128 sum = _mm_setzero_ps ();
|
||||
|
@ -83,7 +84,7 @@ inner_product_gfloat_cubic_1_sse (gfloat * o, const gfloat * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gfloat_none_2_sse (gfloat * o, const gfloat * a,
|
||||
const gfloat * b, gint len, const gfloat * icoeff, gint oversample)
|
||||
const gfloat * b, gint len, const gfloat * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128 sum = _mm_setzero_ps (), t;
|
||||
|
@ -121,7 +122,7 @@ MAKE_RESAMPLE_FUNC (gfloat, none, 2, sse);
|
|||
|
||||
static inline void
|
||||
inner_product_gint16_none_1_sse2 (gint16 * o, const gint16 * a,
|
||||
const gint16 * b, gint len, const gint16 * icoeff, gint oversample)
|
||||
const gint16 * b, gint len, const gint16 * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128i sum, ta, tb;
|
||||
|
@ -149,7 +150,7 @@ inner_product_gint16_none_1_sse2 (gint16 * o, const gint16 * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gint16_linear_1_sse2 (gint16 * o, const gint16 * a,
|
||||
const gint16 * b, gint len, const gint16 * icoeff, gint oversample)
|
||||
const gint16 * b, gint len, const gint16 * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128i sum, t, ta, tb;
|
||||
|
@ -193,7 +194,7 @@ inner_product_gint16_linear_1_sse2 (gint16 * o, const gint16 * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gint16_cubic_1_sse2 (gint16 * o, const gint16 * a,
|
||||
const gint16 * b, gint len, const gint16 * icoeff, gint oversample)
|
||||
const gint16 * b, gint len, const gint16 * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128i sum, ta, tb;
|
||||
|
@ -230,7 +231,7 @@ inner_product_gint16_cubic_1_sse2 (gint16 * o, const gint16 * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gdouble_none_1_sse2 (gdouble * o, const gdouble * a,
|
||||
const gdouble * b, gint len, const gdouble * icoeff, gint oversample)
|
||||
const gdouble * b, gint len, const gdouble * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128d sum = _mm_setzero_pd ();
|
||||
|
@ -255,7 +256,7 @@ inner_product_gdouble_none_1_sse2 (gdouble * o, const gdouble * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gdouble_linear_1_sse2 (gdouble * o, const gdouble * a,
|
||||
const gdouble * b, gint len, const gdouble * icoeff, gint oversample)
|
||||
const gdouble * b, gint len, const gdouble * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128d sum = _mm_setzero_pd ();
|
||||
|
@ -274,7 +275,7 @@ inner_product_gdouble_linear_1_sse2 (gdouble * o, const gdouble * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gdouble_cubic_1_sse2 (gdouble * o, const gdouble * a,
|
||||
const gdouble * b, gint len, const gdouble * icoeff, gint oversample)
|
||||
const gdouble * b, gint len, const gdouble * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128d sum1 = _mm_setzero_pd (), t;
|
||||
|
@ -300,7 +301,7 @@ inner_product_gdouble_cubic_1_sse2 (gdouble * o, const gdouble * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gint16_none_2_sse2 (gint16 * o, const gint16 * a,
|
||||
const gint16 * b, gint len, const gint16 * icoeff, gint oversample)
|
||||
const gint16 * b, gint len, const gint16 * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128i sum, ta, tb, t1;
|
||||
|
@ -332,7 +333,7 @@ inner_product_gint16_none_2_sse2 (gint16 * o, const gint16 * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gdouble_none_2_sse2 (gdouble * o, const gdouble * a,
|
||||
const gdouble * b, gint len, const gdouble * icoeff, gint oversample)
|
||||
const gdouble * b, gint len, const gdouble * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128d sum = _mm_setzero_pd (), t;
|
||||
|
@ -368,6 +369,45 @@ MAKE_RESAMPLE_FUNC (gdouble, cubic, 1, sse2);
|
|||
MAKE_RESAMPLE_FUNC (gint16, none, 2, sse2);
|
||||
MAKE_RESAMPLE_FUNC (gdouble, none, 2, sse2);
|
||||
|
||||
static void
|
||||
interpolate_gdouble_linear_sse2 (gdouble * o, const gdouble * a,
|
||||
gint len, const gdouble * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128d f = _mm_loadu_pd (icoeff), t1, t2;
|
||||
|
||||
for (; i < len; i += 2) {
|
||||
t1 = _mm_mul_pd (_mm_load_pd (a + 2*i + 0), f);
|
||||
t1 = _mm_add_sd (t1, _mm_unpackhi_pd (t1, t1));
|
||||
t2 = _mm_mul_pd (_mm_load_pd (a + 2*i + 2), f);
|
||||
t2 = _mm_add_sd (t2, _mm_unpackhi_pd (t2, t2));
|
||||
|
||||
_mm_store_pd (o + i, _mm_unpacklo_pd (t1, t2));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
interpolate_gdouble_cubic_sse2 (gdouble * o, const gdouble * a,
|
||||
gint len, const gdouble * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128d t1, t2;
|
||||
__m128d f1 = _mm_loadu_pd (icoeff);
|
||||
__m128d f2 = _mm_loadu_pd (icoeff+2);
|
||||
|
||||
for (; i < len; i += 2) {
|
||||
t1 = _mm_add_pd (_mm_mul_pd (_mm_load_pd (a + 4*i + 0), f1),
|
||||
_mm_mul_pd (_mm_load_pd (a + 4*i + 2), f2));
|
||||
t1 = _mm_add_sd (t1, _mm_unpackhi_pd (t1, t1));
|
||||
|
||||
t2 = _mm_add_pd (_mm_mul_pd (_mm_load_pd (a + 4*i + 4), f1),
|
||||
_mm_mul_pd (_mm_load_pd (a + 4*i + 6), f2));
|
||||
t2 = _mm_add_sd (t2, _mm_unpackhi_pd (t2, t2));
|
||||
|
||||
_mm_store_pd (o + i, _mm_unpacklo_pd (t1, t2));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_SMMINTRIN_H) && defined(__SSE4_1__)
|
||||
|
@ -375,7 +415,7 @@ MAKE_RESAMPLE_FUNC (gdouble, none, 2, sse2);
|
|||
|
||||
static inline void
|
||||
inner_product_gint32_none_1_sse41 (gint32 * o, const gint32 * a,
|
||||
const gint32 * b, gint len, const gint32 * icoeff, gint oversample)
|
||||
const gint32 * b, gint len, const gint32 * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
__m128i sum, ta, tb;
|
||||
|
@ -413,7 +453,7 @@ inner_product_gint32_none_1_sse41 (gint32 * o, const gint32 * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gint32_linear_1_sse41 (gint32 * o, const gint32 * a,
|
||||
const gint32 * b, gint len, const gint32 * icoeff, gint oversample)
|
||||
const gint32 * b, gint len, const gint32 * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
gint64 res;
|
||||
|
@ -457,7 +497,7 @@ inner_product_gint32_linear_1_sse41 (gint32 * o, const gint32 * a,
|
|||
|
||||
static inline void
|
||||
inner_product_gint32_cubic_1_sse41 (gint32 * o, const gint32 * a,
|
||||
const gint32 * b, gint len, const gint32 * icoeff, gint oversample)
|
||||
const gint32 * b, gint len, const gint32 * icoeff)
|
||||
{
|
||||
gint i = 0;
|
||||
gint64 res;
|
||||
|
@ -537,6 +577,9 @@ audio_resampler_check_x86 (const gchar *option)
|
|||
resample_gint16_none_2 = resample_gint16_none_2_sse2;
|
||||
resample_gfloat_none_2 = resample_gfloat_none_2_sse;
|
||||
resample_gdouble_none_2 = resample_gdouble_none_2_sse2;
|
||||
|
||||
interpolate_gdouble_linear = interpolate_gdouble_linear_sse2;
|
||||
interpolate_gdouble_cubic = interpolate_gdouble_cubic_sse2;
|
||||
#else
|
||||
GST_DEBUG ("SSE2 optimisations not enabled");
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -74,15 +74,19 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
|
|||
#undef USE_SPEEX
|
||||
|
||||
#define DEFAULT_QUALITY GST_AUDIO_RESAMPLER_QUALITY_DEFAULT
|
||||
#define DEFAULT_RESAMPLE_METHOD GST_AUDIO_RESAMPLER_METHOD_KAISER
|
||||
#define DEFAULT_SINC_FILTER_MODE GST_AUDIO_RESAMPLER_FILTER_MODE_AUTO
|
||||
#define DEFAULT_SINC_FILTER_AUTO_THRESHOLD (1*1048576)
|
||||
#define DEFAULT_SINC_FILTER_INTERPOLATION GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_CUBIC
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_QUALITY,
|
||||
PROP_RESAMPLE_METHOD,
|
||||
PROP_SINC_FILTER_MODE,
|
||||
PROP_SINC_FILTER_AUTO_THRESHOLD
|
||||
PROP_SINC_FILTER_AUTO_THRESHOLD,
|
||||
PROP_SINC_FILTER_INTERPOLATION
|
||||
};
|
||||
|
||||
#define SUPPORTED_CAPS \
|
||||
|
@ -150,6 +154,11 @@ gst_audio_resample_class_init (GstAudioResampleClass * klass)
|
|||
DEFAULT_QUALITY,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_RESAMPLE_METHOD,
|
||||
g_param_spec_enum ("resample-method", "Resample method to use",
|
||||
"What resample method to use",
|
||||
GST_TYPE_AUDIO_RESAMPLER_METHOD,
|
||||
DEFAULT_RESAMPLE_METHOD, G_PARAM_READWRITE | 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",
|
||||
|
@ -164,6 +173,14 @@ gst_audio_resample_class_init (GstAudioResampleClass * klass)
|
|||
"Memory usage threshold to use if sinc filter mode is AUTO, given in bytes",
|
||||
0, G_MAXUINT, DEFAULT_SINC_FILTER_AUTO_THRESHOLD,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SINC_FILTER_INTERPOLATION,
|
||||
g_param_spec_enum ("sinc-filter-interpolation",
|
||||
"Sinc filter interpolation",
|
||||
"How to interpolate the sinc filter table",
|
||||
GST_TYPE_AUDIO_RESAMPLER_FILTER_INTERPOLATION,
|
||||
DEFAULT_SINC_FILTER_INTERPOLATION,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gst_element_class_add_static_pad_template (gstelement_class,
|
||||
&gst_audio_resample_src_template);
|
||||
|
@ -205,10 +222,11 @@ gst_audio_resample_init (GstAudioResample * resample)
|
|||
{
|
||||
GstBaseTransform *trans = GST_BASE_TRANSFORM (resample);
|
||||
|
||||
resample->method = GST_AUDIO_RESAMPLER_METHOD_KAISER;
|
||||
resample->method = DEFAULT_RESAMPLE_METHOD;
|
||||
resample->quality = DEFAULT_QUALITY;
|
||||
resample->sinc_filter_mode = DEFAULT_SINC_FILTER_MODE;
|
||||
resample->sinc_filter_auto_threshold = DEFAULT_SINC_FILTER_AUTO_THRESHOLD;
|
||||
resample->sinc_filter_interpolation = DEFAULT_SINC_FILTER_INTERPOLATION;
|
||||
|
||||
gst_base_transform_set_gap_aware (trans, TRUE);
|
||||
gst_pad_set_query_function (trans->srcpad, gst_audio_resample_query);
|
||||
|
@ -357,7 +375,10 @@ make_options (GstAudioResample * resample, GstAudioInfo * in,
|
|||
resample->method,
|
||||
GST_AUDIO_RESAMPLER_OPT_FILTER_MODE, GST_TYPE_AUDIO_RESAMPLER_FILTER_MODE,
|
||||
resample->sinc_filter_mode, GST_AUDIO_RESAMPLER_OPT_FILTER_MODE_THRESHOLD,
|
||||
G_TYPE_UINT, resample->sinc_filter_auto_threshold, NULL);
|
||||
G_TYPE_UINT, resample->sinc_filter_auto_threshold,
|
||||
GST_AUDIO_RESAMPLER_OPT_FILTER_INTERPOLATION,
|
||||
GST_TYPE_AUDIO_RESAMPLER_FILTER_INTERPOLATION,
|
||||
resample->sinc_filter_interpolation, NULL);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
@ -999,6 +1020,10 @@ gst_audio_resample_set_property (GObject * object, guint prop_id,
|
|||
GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality);
|
||||
gst_audio_resample_update_state (resample, NULL, NULL);
|
||||
break;
|
||||
case PROP_RESAMPLE_METHOD:
|
||||
resample->method = g_value_get_enum (value);
|
||||
gst_audio_resample_update_state (resample, NULL, NULL);
|
||||
break;
|
||||
case PROP_SINC_FILTER_MODE:
|
||||
/* FIXME locking! */
|
||||
resample->sinc_filter_mode = g_value_get_enum (value);
|
||||
|
@ -1009,6 +1034,11 @@ gst_audio_resample_set_property (GObject * object, guint prop_id,
|
|||
resample->sinc_filter_auto_threshold = g_value_get_uint (value);
|
||||
gst_audio_resample_update_state (resample, NULL, NULL);
|
||||
break;
|
||||
case PROP_SINC_FILTER_INTERPOLATION:
|
||||
/* FIXME locking! */
|
||||
resample->sinc_filter_interpolation = g_value_get_enum (value);
|
||||
gst_audio_resample_update_state (resample, NULL, NULL);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -1027,12 +1057,18 @@ gst_audio_resample_get_property (GObject * object, guint prop_id,
|
|||
case PROP_QUALITY:
|
||||
g_value_set_int (value, resample->quality);
|
||||
break;
|
||||
case PROP_RESAMPLE_METHOD:
|
||||
g_value_set_enum (value, resample->method);
|
||||
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;
|
||||
case PROP_SINC_FILTER_INTERPOLATION:
|
||||
g_value_set_enum (value, resample->sinc_filter_interpolation);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -67,6 +67,7 @@ struct _GstAudioResample {
|
|||
gint quality;
|
||||
GstAudioResamplerFilterMode sinc_filter_mode;
|
||||
guint32 sinc_filter_auto_threshold;
|
||||
GstAudioResamplerFilterInterpolation sinc_filter_interpolation;
|
||||
|
||||
/* state */
|
||||
GstAudioInfo in;
|
||||
|
|
Loading…
Reference in a new issue