mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
Add support for double samples as input and refactor the usage of the different compilation flavors of the speex resa...
Original commit message from CVS: * gst/speexresample/Makefile.am: * gst/speexresample/arch.h: * gst/speexresample/gstspeexresample.c: (gst_speex_resample_stop), (gst_speex_resample_get_unit_size), (gst_speex_resample_get_funcs), (gst_speex_resample_init_state), (gst_speex_resample_update_state), (gst_speex_resample_reset_state), (gst_speex_resample_parse_caps), (_gcd), (gst_speex_resample_transform_size), (gst_speex_resample_set_caps), (gst_speex_resample_push_drain), (gst_speex_resample_process), (gst_speex_resample_transform), (gst_speex_resample_query), (gst_speex_resample_set_property): * gst/speexresample/gstspeexresample.h: * gst/speexresample/resample.c: * gst/speexresample/speex_resampler.h: * gst/speexresample/speex_resampler_double.c: * gst/speexresample/speex_resampler_wrapper.h: * tests/check/elements/speexresample.c: (setup_speexresample), (test_perfect_stream_instance), (GST_START_TEST), (test_discont_stream_instance): Add support for double samples as input and refactor the usage of the different compilation flavors of the speex resampler.
This commit is contained in:
parent
51262eeb4c
commit
12766882b5
10 changed files with 393 additions and 188 deletions
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
|||
2008-10-30 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
|
||||
* gst/speexresample/Makefile.am:
|
||||
* gst/speexresample/arch.h:
|
||||
* gst/speexresample/gstspeexresample.c: (gst_speex_resample_stop),
|
||||
(gst_speex_resample_get_unit_size), (gst_speex_resample_get_funcs),
|
||||
(gst_speex_resample_init_state), (gst_speex_resample_update_state),
|
||||
(gst_speex_resample_reset_state), (gst_speex_resample_parse_caps),
|
||||
(_gcd), (gst_speex_resample_transform_size),
|
||||
(gst_speex_resample_set_caps), (gst_speex_resample_push_drain),
|
||||
(gst_speex_resample_process), (gst_speex_resample_transform),
|
||||
(gst_speex_resample_query), (gst_speex_resample_set_property):
|
||||
* gst/speexresample/gstspeexresample.h:
|
||||
* gst/speexresample/resample.c:
|
||||
* gst/speexresample/speex_resampler.h:
|
||||
* gst/speexresample/speex_resampler_double.c:
|
||||
* gst/speexresample/speex_resampler_wrapper.h:
|
||||
* tests/check/elements/speexresample.c: (setup_speexresample),
|
||||
(test_perfect_stream_instance), (GST_START_TEST),
|
||||
(test_discont_stream_instance):
|
||||
Add support for double samples as input and refactor the usage
|
||||
of the different compilation flavors of the speex resampler.
|
||||
|
||||
2008-10-30 Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
* gst/scaletempo/gstscaletempo.c:
|
||||
|
|
|
@ -3,7 +3,8 @@ plugin_LTLIBRARIES = libgstspeexresample.la
|
|||
libgstspeexresample_la_SOURCES = \
|
||||
gstspeexresample.c \
|
||||
speex_resampler_int.c \
|
||||
speex_resampler_float.c
|
||||
speex_resampler_float.c \
|
||||
speex_resampler_double.c
|
||||
|
||||
libgstspeexresample_la_CFLAGS = \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||
|
|
|
@ -137,6 +137,28 @@ typedef spx_word32_t spx_sig_t;
|
|||
|
||||
#else
|
||||
|
||||
#ifdef DOUBLE_PRECISION
|
||||
typedef double spx_mem_t;
|
||||
typedef double spx_coef_t;
|
||||
typedef double spx_lsp_t;
|
||||
typedef double spx_sig_t;
|
||||
typedef double spx_word16_t;
|
||||
typedef double spx_word32_t;
|
||||
|
||||
#define Q15ONE 1.0
|
||||
#define LPC_SCALING 1.
|
||||
#define SIG_SCALING 1.
|
||||
#define LSP_SCALING 1.
|
||||
#define GAMMA_SCALING 1.
|
||||
#define GAIN_SCALING 1.
|
||||
#define GAIN_SCALING_1 1.
|
||||
|
||||
|
||||
#define VERY_SMALL 1e-20
|
||||
#define VERY_LARGE32 1e20
|
||||
#define VERY_LARGE16 1e20
|
||||
#define Q15_ONE ((spx_word16_t)1.)
|
||||
#else /* !DOUBLE_PRECISION */
|
||||
typedef float spx_mem_t;
|
||||
typedef float spx_coef_t;
|
||||
typedef float spx_lsp_t;
|
||||
|
@ -157,6 +179,7 @@ typedef float spx_word32_t;
|
|||
#define VERY_LARGE32 1e15f
|
||||
#define VERY_LARGE16 1e15f
|
||||
#define Q15_ONE ((spx_word16_t)1.f)
|
||||
#endif /* DOUBLE_PRECISION */
|
||||
|
||||
#define QCONST16(x,bits) (x)
|
||||
#define QCONST32(x,bits) (x)
|
||||
|
|
|
@ -60,7 +60,7 @@ GST_STATIC_CAPS ( \
|
|||
"rate = (int) [ 1, MAX ], " \
|
||||
"channels = (int) [ 1, MAX ], " \
|
||||
"endianness = (int) BYTE_ORDER, " \
|
||||
"width = (int) 32; " \
|
||||
"width = (int) { 32, 64 }; " \
|
||||
"audio/x-raw-int, " \
|
||||
"rate = (int) [ 1, MAX ], " \
|
||||
"channels = (int) [ 1, MAX ], " \
|
||||
|
@ -196,10 +196,12 @@ gst_speex_resample_stop (GstBaseTransform * base)
|
|||
GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base);
|
||||
|
||||
if (resample->state) {
|
||||
resample_resampler_destroy (resample->state);
|
||||
resample->funcs->destroy (resample->state);
|
||||
resample->state = NULL;
|
||||
}
|
||||
|
||||
resample->funcs = NULL;
|
||||
|
||||
gst_caps_replace (&resample->sinkcaps, NULL);
|
||||
gst_caps_replace (&resample->srccaps, NULL);
|
||||
|
||||
|
@ -224,7 +226,7 @@ gst_speex_resample_get_unit_size (GstBaseTransform * base, GstCaps * caps,
|
|||
if (G_UNLIKELY (!ret))
|
||||
return FALSE;
|
||||
|
||||
*size = gst_util_uint64_scale (width, channels, 8);
|
||||
*size = (width / 8) * channels;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -261,38 +263,47 @@ gst_speex_resample_fixate_caps (GstBaseTransform * base,
|
|||
gst_structure_fixate_field_nearest_int (s, "rate", rate);
|
||||
}
|
||||
|
||||
static const SpeexResampleFuncs *
|
||||
gst_speex_resample_get_funcs (gint width, gboolean fp)
|
||||
{
|
||||
const SpeexResampleFuncs *funcs = NULL;
|
||||
|
||||
if (width == 16 && !fp)
|
||||
funcs = &int_funcs;
|
||||
else if (width == 32 && fp)
|
||||
funcs = &float_funcs;
|
||||
else if (width == 64 && fp)
|
||||
funcs = &double_funcs;
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
||||
static SpeexResamplerState *
|
||||
gst_speex_resample_init_state (gint channels, gint inrate, gint outrate,
|
||||
gint quality, gboolean fp)
|
||||
gst_speex_resample_init_state (GstSpeexResample * resample, gint width,
|
||||
gint channels, gint inrate, gint outrate, gint quality, gboolean fp)
|
||||
{
|
||||
SpeexResamplerState *ret = NULL;
|
||||
gint err = RESAMPLER_ERR_SUCCESS;
|
||||
const SpeexResampleFuncs *funcs = gst_speex_resample_get_funcs (width, fp);
|
||||
|
||||
if (fp)
|
||||
ret =
|
||||
resample_float_resampler_init (channels, inrate, outrate, quality,
|
||||
&err);
|
||||
else
|
||||
ret =
|
||||
resample_int_resampler_init (channels, inrate, outrate, quality, &err);
|
||||
ret = funcs->init (channels, inrate, outrate, quality, &err);
|
||||
|
||||
if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
|
||||
GST_ERROR ("Failed to create resampler state: %s",
|
||||
resample_resampler_strerror (err));
|
||||
GST_ERROR_OBJECT (resample, "Failed to create resampler state: %s",
|
||||
funcs->strerror (err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fp)
|
||||
resample_float_resampler_skip_zeros (ret);
|
||||
else
|
||||
resample_int_resampler_skip_zeros (ret);
|
||||
funcs->skip_zeros (ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_speex_resample_update_state (GstSpeexResample * resample, gint channels,
|
||||
gint inrate, gint outrate, gint quality, gboolean fp)
|
||||
gst_speex_resample_update_state (GstSpeexResample * resample, gint width,
|
||||
gint channels, gint inrate, gint outrate, gint quality, gboolean fp)
|
||||
{
|
||||
gboolean ret = TRUE;
|
||||
gboolean updated_latency = FALSE;
|
||||
|
@ -302,41 +313,38 @@ gst_speex_resample_update_state (GstSpeexResample * resample, gint channels,
|
|||
|
||||
if (resample->state == NULL) {
|
||||
ret = TRUE;
|
||||
} else if (resample->channels != channels || fp != resample->fp) {
|
||||
resample_resampler_destroy (resample->state);
|
||||
} else if (resample->channels != channels || fp != resample->fp
|
||||
|| width != resample->width) {
|
||||
resample->funcs->destroy (resample->state);
|
||||
resample->state =
|
||||
gst_speex_resample_init_state (channels, inrate, outrate, quality, fp);
|
||||
gst_speex_resample_init_state (resample, width, channels, inrate,
|
||||
outrate, quality, fp);
|
||||
|
||||
resample->funcs = gst_speex_resample_get_funcs (width, fp);
|
||||
ret = (resample->state != NULL);
|
||||
} else if (resample->inrate != inrate || resample->outrate != outrate) {
|
||||
gint err = RESAMPLER_ERR_SUCCESS;
|
||||
|
||||
if (fp)
|
||||
err =
|
||||
resample_float_resampler_set_rate (resample->state, inrate, outrate);
|
||||
else
|
||||
err = resample_int_resampler_set_rate (resample->state, inrate, outrate);
|
||||
err = resample->funcs->set_rate (resample->state, inrate, outrate);
|
||||
|
||||
if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS))
|
||||
GST_ERROR_OBJECT (resample, "Failed to update rate: %s",
|
||||
resample_resampler_strerror (err));
|
||||
resample->funcs->strerror (err));
|
||||
|
||||
ret = (err == RESAMPLER_ERR_SUCCESS);
|
||||
} else if (quality != resample->quality) {
|
||||
gint err = RESAMPLER_ERR_SUCCESS;
|
||||
|
||||
if (fp)
|
||||
err = resample_float_resampler_set_quality (resample->state, quality);
|
||||
else
|
||||
err = resample_int_resampler_set_quality (resample->state, quality);
|
||||
err = resample->funcs->set_quality (resample->state, quality);
|
||||
|
||||
if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS))
|
||||
GST_ERROR_OBJECT (resample, "Failed to update quality: %s",
|
||||
resample_resampler_strerror (err));
|
||||
resample->funcs->strerror (err));
|
||||
|
||||
ret = (err == RESAMPLER_ERR_SUCCESS);
|
||||
}
|
||||
|
||||
resample->width = width;
|
||||
resample->channels = channels;
|
||||
resample->fp = fp;
|
||||
resample->quality = quality;
|
||||
|
@ -353,20 +361,18 @@ gst_speex_resample_update_state (GstSpeexResample * resample, gint channels,
|
|||
static void
|
||||
gst_speex_resample_reset_state (GstSpeexResample * resample)
|
||||
{
|
||||
if (resample->state && resample->fp)
|
||||
resample_float_resampler_reset_mem (resample->state);
|
||||
else if (resample->state && !resample->fp)
|
||||
resample_int_resampler_reset_mem (resample->state);
|
||||
if (resample->state)
|
||||
resample->funcs->reset_mem (resample->state);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_speex_resample_parse_caps (GstCaps * incaps,
|
||||
GstCaps * outcaps, gint * channels, gint * inrate, gint * outrate,
|
||||
gboolean * fp)
|
||||
GstCaps * outcaps, gint * width, gint * channels, gint * inrate,
|
||||
gint * outrate, gboolean * fp)
|
||||
{
|
||||
GstStructure *structure;
|
||||
gboolean ret;
|
||||
gint myinrate, myoutrate, mychannels;
|
||||
gint mywidth, myinrate, myoutrate, mychannels;
|
||||
gboolean myfp;
|
||||
|
||||
GST_DEBUG ("incaps %" GST_PTR_FORMAT ", outcaps %"
|
||||
|
@ -381,6 +387,7 @@ gst_speex_resample_parse_caps (GstCaps * incaps,
|
|||
|
||||
ret = gst_structure_get_int (structure, "rate", &myinrate);
|
||||
ret &= gst_structure_get_int (structure, "channels", &mychannels);
|
||||
ret &= gst_structure_get_int (structure, "width", &mywidth);
|
||||
if (G_UNLIKELY (!ret))
|
||||
goto no_in_rate_channels;
|
||||
|
||||
|
@ -395,7 +402,8 @@ gst_speex_resample_parse_caps (GstCaps * incaps,
|
|||
*inrate = myinrate;
|
||||
if (outrate)
|
||||
*outrate = myoutrate;
|
||||
|
||||
if (width)
|
||||
*width = mywidth;
|
||||
if (fp)
|
||||
*fp = myfp;
|
||||
|
||||
|
@ -414,18 +422,30 @@ no_out_rate:
|
|||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
_gcd (gint a, gint b)
|
||||
{
|
||||
while (b != 0) {
|
||||
int temp = a;
|
||||
|
||||
a = b;
|
||||
b = temp % b;
|
||||
}
|
||||
|
||||
return ABS (a);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_speex_resample_transform_size (GstBaseTransform * base,
|
||||
GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps,
|
||||
guint * othersize)
|
||||
{
|
||||
GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base);
|
||||
SpeexResamplerState *state;
|
||||
GstCaps *srccaps, *sinkcaps;
|
||||
gboolean use_internal = FALSE; /* whether we use the internal state */
|
||||
gboolean ret = TRUE;
|
||||
guint32 ratio_den, ratio_num;
|
||||
gboolean fp;
|
||||
gint inrate, outrate, gcd;
|
||||
gint width;
|
||||
|
||||
GST_LOG_OBJECT (resample, "asked to transform size %d in direction %s",
|
||||
size, direction == GST_PAD_SINK ? "SINK" : "SRC");
|
||||
|
@ -437,60 +457,40 @@ gst_speex_resample_transform_size (GstBaseTransform * base,
|
|||
srccaps = caps;
|
||||
}
|
||||
|
||||
/* if the caps are the ones that _set_caps got called with; we can use
|
||||
* our own state; otherwise we'll have to create a state */
|
||||
if (resample->state && gst_caps_is_equal (sinkcaps, resample->sinkcaps) &&
|
||||
gst_caps_is_equal (srccaps, resample->srccaps)) {
|
||||
use_internal = TRUE;
|
||||
state = resample->state;
|
||||
fp = resample->fp;
|
||||
} else {
|
||||
gint inrate, outrate, channels;
|
||||
|
||||
GST_DEBUG_OBJECT (resample, "Can't use internal state, creating state");
|
||||
|
||||
ret =
|
||||
gst_speex_resample_parse_caps (caps, othercaps, &channels, &inrate,
|
||||
&outrate, &fp);
|
||||
|
||||
if (G_UNLIKELY (!ret)) {
|
||||
GST_ERROR_OBJECT (resample, "Wrong caps");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
state = gst_speex_resample_init_state (channels, inrate, outrate, 0, TRUE);
|
||||
if (G_UNLIKELY (!state))
|
||||
return FALSE;
|
||||
ret =
|
||||
gst_speex_resample_parse_caps (caps, othercaps, &width, NULL, &inrate,
|
||||
&outrate, NULL);
|
||||
if (G_UNLIKELY (!ret)) {
|
||||
GST_ERROR_OBJECT (resample, "Wrong caps");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (resample->fp || use_internal)
|
||||
resample_float_resampler_get_ratio (state, &ratio_num, &ratio_den);
|
||||
else
|
||||
resample_int_resampler_get_ratio (state, &ratio_num, &ratio_den);
|
||||
gcd = _gcd (inrate, outrate);
|
||||
ratio_num = inrate / gcd;
|
||||
ratio_den = outrate / gcd;
|
||||
|
||||
if (direction == GST_PAD_SINK) {
|
||||
gint fac = (fp) ? 4 : 2;
|
||||
gint fac = width / 8;
|
||||
|
||||
/* asked to convert size of an incoming buffer */
|
||||
size /= fac;
|
||||
*othersize = (size * ratio_den + (ratio_num >> 1)) / ratio_num;
|
||||
//*othersize = (size * ratio_den + (ratio_num >> 1)) / ratio_num;
|
||||
*othersize = (size * ratio_den + ratio_num - 1) / ratio_num;
|
||||
*othersize *= fac;
|
||||
size *= fac;
|
||||
} else {
|
||||
gint fac = (fp) ? 4 : 2;
|
||||
gint fac = width / 8;
|
||||
|
||||
/* asked to convert size of an outgoing buffer */
|
||||
size /= fac;
|
||||
*othersize = (size * ratio_num + (ratio_den >> 1)) / ratio_den;
|
||||
//*othersize = (size * ratio_num + (ratio_den >> 1)) / ratio_den;
|
||||
*othersize = (size * ratio_num + ratio_den - 1) / ratio_den;
|
||||
*othersize *= fac;
|
||||
size *= fac;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (resample, "transformed size %d to %d", size, *othersize);
|
||||
|
||||
if (!use_internal)
|
||||
resample_resampler_destroy (state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -499,22 +499,22 @@ gst_speex_resample_set_caps (GstBaseTransform * base, GstCaps * incaps,
|
|||
GstCaps * outcaps)
|
||||
{
|
||||
gboolean ret;
|
||||
gint inrate = 0, outrate = 0, channels = 0;
|
||||
gboolean fp = FALSE;
|
||||
gint width = 0, inrate = 0, outrate = 0, channels = 0;
|
||||
gboolean fp;
|
||||
GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base);
|
||||
|
||||
GST_LOG ("incaps %" GST_PTR_FORMAT ", outcaps %"
|
||||
GST_PTR_FORMAT, incaps, outcaps);
|
||||
|
||||
ret = gst_speex_resample_parse_caps (incaps, outcaps,
|
||||
&channels, &inrate, &outrate, &fp);
|
||||
&width, &channels, &inrate, &outrate, &fp);
|
||||
|
||||
if (G_UNLIKELY (!ret))
|
||||
return FALSE;
|
||||
|
||||
ret =
|
||||
gst_speex_resample_update_state (resample, channels, inrate, outrate,
|
||||
resample->quality, fp);
|
||||
gst_speex_resample_update_state (resample, width, channels, inrate,
|
||||
outrate, resample->quality, fp);
|
||||
|
||||
if (G_UNLIKELY (!ret))
|
||||
return FALSE;
|
||||
|
@ -536,27 +536,16 @@ gst_speex_resample_push_drain (GstSpeexResample * resample)
|
|||
gint outsize;
|
||||
guint out_len, out_processed;
|
||||
gint err;
|
||||
guint num, den, len;
|
||||
|
||||
if (!resample->state)
|
||||
return;
|
||||
|
||||
if (resample->fp) {
|
||||
guint num, den;
|
||||
resample->funcs->get_ratio (resample->state, &num, &den);
|
||||
|
||||
resample_float_resampler_get_ratio (resample->state, &num, &den);
|
||||
|
||||
out_len = resample_float_resampler_get_input_latency (resample->state);
|
||||
out_len = out_processed = (out_len * den + (num >> 1)) / num;
|
||||
outsize = 4 * out_len * resample->channels;
|
||||
} else {
|
||||
guint num, den;
|
||||
|
||||
resample_int_resampler_get_ratio (resample->state, &num, &den);
|
||||
|
||||
out_len = resample_int_resampler_get_input_latency (resample->state);
|
||||
out_len = out_processed = (out_len * den + (num >> 1)) / num;
|
||||
outsize = 2 * out_len * resample->channels;
|
||||
}
|
||||
out_len = resample->funcs->get_input_latency (resample->state);
|
||||
out_len = out_processed = (out_len * den + (num >> 1)) / num;
|
||||
outsize = (resample->width / 8) * out_len * resample->channels;
|
||||
|
||||
res =
|
||||
gst_pad_alloc_buffer_and_set_caps (trans->srcpad, GST_BUFFER_OFFSET_NONE,
|
||||
|
@ -568,23 +557,15 @@ gst_speex_resample_push_drain (GstSpeexResample * resample)
|
|||
return;
|
||||
}
|
||||
|
||||
if (resample->fp) {
|
||||
guint len = resample_float_resampler_get_input_latency (resample->state);
|
||||
len = resample->funcs->get_input_latency (resample->state);
|
||||
|
||||
err =
|
||||
resample_float_resampler_process_interleaved_float (resample->state,
|
||||
NULL, &len, (gfloat *) GST_BUFFER_DATA (buf), &out_processed);
|
||||
} else {
|
||||
guint len = resample_int_resampler_get_input_latency (resample->state);
|
||||
|
||||
err =
|
||||
resample_int_resampler_process_interleaved_int (resample->state, NULL,
|
||||
&len, (gint16 *) GST_BUFFER_DATA (buf), &out_processed);
|
||||
}
|
||||
err =
|
||||
resample->funcs->process (resample->state,
|
||||
NULL, &len, (guint8 *) GST_BUFFER_DATA (buf), &out_processed);
|
||||
|
||||
if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
|
||||
GST_WARNING_OBJECT (resample, "Failed to process drain: %s",
|
||||
resample_resampler_strerror (err));
|
||||
resample->funcs->strerror (err));
|
||||
gst_buffer_unref (buf);
|
||||
return;
|
||||
}
|
||||
|
@ -598,7 +579,7 @@ gst_speex_resample_push_drain (GstSpeexResample * resample)
|
|||
GST_BUFFER_DURATION (buf) =
|
||||
GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate);
|
||||
GST_BUFFER_SIZE (buf) =
|
||||
out_processed * resample->channels * ((resample->fp) ? 4 : 2);
|
||||
out_processed * resample->channels * (resample->width / 8);
|
||||
|
||||
if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
|
||||
GST_BUFFER_OFFSET (buf) = resample->next_offset;
|
||||
|
@ -693,25 +674,15 @@ gst_speex_resample_process (GstSpeexResample * resample, GstBuffer * inbuf,
|
|||
in_len = GST_BUFFER_SIZE (inbuf) / resample->channels;
|
||||
out_len = GST_BUFFER_SIZE (outbuf) / resample->channels;
|
||||
|
||||
if (resample->fp) {
|
||||
in_len /= 4;
|
||||
out_len /= 4;
|
||||
} else {
|
||||
in_len /= 2;
|
||||
out_len /= 2;
|
||||
}
|
||||
in_len /= (resample->width / 8);
|
||||
out_len /= (resample->width / 8);
|
||||
|
||||
in_processed = in_len;
|
||||
out_processed = out_len;
|
||||
|
||||
if (resample->fp)
|
||||
err = resample_float_resampler_process_interleaved_float (resample->state,
|
||||
(const gfloat *) GST_BUFFER_DATA (inbuf), &in_processed,
|
||||
(gfloat *) GST_BUFFER_DATA (outbuf), &out_processed);
|
||||
else
|
||||
err = resample_int_resampler_process_interleaved_int (resample->state,
|
||||
(const gint16 *) GST_BUFFER_DATA (inbuf), &in_processed,
|
||||
(gint16 *) GST_BUFFER_DATA (outbuf), &out_processed);
|
||||
err = resample->funcs->process (resample->state,
|
||||
(const guint8 *) GST_BUFFER_DATA (inbuf), &in_processed,
|
||||
(guint8 *) GST_BUFFER_DATA (outbuf), &out_processed);
|
||||
|
||||
if (G_UNLIKELY (in_len != in_processed))
|
||||
GST_WARNING_OBJECT (resample, "Converted %d of %d input samples",
|
||||
|
@ -738,13 +709,13 @@ gst_speex_resample_process (GstSpeexResample * resample, GstBuffer * inbuf,
|
|||
|
||||
if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
|
||||
GST_ERROR_OBJECT (resample, "Failed to convert data: %s",
|
||||
resample_resampler_strerror (err));
|
||||
resample->funcs->strerror (err));
|
||||
return GST_FLOW_ERROR;
|
||||
} else {
|
||||
GST_BUFFER_DURATION (outbuf) =
|
||||
GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate);
|
||||
GST_BUFFER_SIZE (outbuf) =
|
||||
out_processed * resample->channels * ((resample->fp) ? 4 : 2);
|
||||
out_processed * resample->channels * (resample->width / 8);
|
||||
|
||||
if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = resample->next_ts;
|
||||
|
@ -778,13 +749,17 @@ gst_speex_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
|
|||
guint outsamples, insamples;
|
||||
GstFlowReturn ret;
|
||||
|
||||
if (resample->state == NULL)
|
||||
if (resample->state == NULL) {
|
||||
if (G_UNLIKELY (!(resample->state =
|
||||
gst_speex_resample_init_state (resample->channels,
|
||||
resample->inrate, resample->outrate, resample->quality,
|
||||
resample->fp))))
|
||||
gst_speex_resample_init_state (resample, resample->width,
|
||||
resample->channels, resample->inrate, resample->outrate,
|
||||
resample->quality, resample->fp))))
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
resample->funcs =
|
||||
gst_speex_resample_get_funcs (resample->width, resample->fp);
|
||||
}
|
||||
|
||||
data = GST_BUFFER_DATA (inbuf);
|
||||
size = GST_BUFFER_SIZE (inbuf);
|
||||
timestamp = GST_BUFFER_TIMESTAMP (inbuf);
|
||||
|
@ -810,10 +785,10 @@ gst_speex_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
|
|||
}
|
||||
|
||||
insamples = GST_BUFFER_SIZE (inbuf) / resample->channels;
|
||||
insamples /= (resample->fp) ? 4 : 2;
|
||||
insamples /= (resample->width / 8);
|
||||
|
||||
outsamples = GST_BUFFER_SIZE (outbuf) / resample->channels;
|
||||
outsamples /= (resample->fp) ? 4 : 2;
|
||||
outsamples /= (resample->width / 8);
|
||||
|
||||
if (GST_CLOCK_TIME_IS_VALID (timestamp)
|
||||
&& !GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
|
||||
|
@ -860,12 +835,9 @@ gst_speex_resample_query (GstPad * pad, GstQuery * query)
|
|||
gint rate = resample->inrate;
|
||||
gint resampler_latency;
|
||||
|
||||
if (resample->state && resample->fp)
|
||||
if (resample->state)
|
||||
resampler_latency =
|
||||
resample_float_resampler_get_input_latency (resample->state);
|
||||
else if (resample->state && !resample->fp)
|
||||
resampler_latency =
|
||||
resample_int_resampler_get_input_latency (resample->state);
|
||||
resample->funcs->get_input_latency (resample->state);
|
||||
else
|
||||
resampler_latency = 0;
|
||||
|
||||
|
@ -936,8 +908,9 @@ gst_speex_resample_set_property (GObject * object, guint prop_id,
|
|||
resample->quality = g_value_get_int (value);
|
||||
GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality);
|
||||
|
||||
gst_speex_resample_update_state (resample, resample->channels,
|
||||
resample->inrate, resample->outrate, resample->quality, resample->fp);
|
||||
gst_speex_resample_update_state (resample, resample->width,
|
||||
resample->channels, resample->inrate, resample->outrate,
|
||||
resample->quality, resample->fp);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
#include <gst/audio/audio.h>
|
||||
|
||||
#include "speex_resampler_wrapper.h"
|
||||
|
||||
|
@ -61,13 +62,15 @@ struct _GstSpeexResample {
|
|||
GstClockTime next_ts;
|
||||
GstClockTime next_upstream_ts;
|
||||
|
||||
gboolean fp;
|
||||
gint channels;
|
||||
gint inrate;
|
||||
gint outrate;
|
||||
gint quality;
|
||||
gint width;
|
||||
gboolean fp;
|
||||
|
||||
SpeexResamplerState *state;
|
||||
const SpeexResampleFuncs *funcs;
|
||||
};
|
||||
|
||||
struct _GstSpeexResampleClass {
|
||||
|
|
|
@ -267,10 +267,17 @@ static const struct QualityMapping quality_map[11] = {
|
|||
};
|
||||
|
||||
/*8,24,40,56,80,104,128,160,200,256,320*/
|
||||
#ifdef DOUBLE_PRECISION
|
||||
static double
|
||||
compute_func (double x, struct FuncDef *func)
|
||||
{
|
||||
double y, frac;
|
||||
#else
|
||||
static double
|
||||
compute_func (float x, struct FuncDef *func)
|
||||
{
|
||||
float y, frac;
|
||||
#endif
|
||||
double interp[4];
|
||||
int ind;
|
||||
y = x * func->oversample;
|
||||
|
@ -321,11 +328,19 @@ sinc (float cutoff, float x, int N, struct FuncDef *window_func)
|
|||
}
|
||||
#else
|
||||
/* The slow way of computing a sinc for the table. Should improve that some day */
|
||||
#ifdef DOUBLE_PRECISION
|
||||
static spx_word16_t
|
||||
sinc (double cutoff, double x, int N, struct FuncDef *window_func)
|
||||
{
|
||||
/*fprintf (stderr, "%f ", x); */
|
||||
double xx = x * cutoff;
|
||||
#else
|
||||
static spx_word16_t
|
||||
sinc (float cutoff, float x, int N, struct FuncDef *window_func)
|
||||
{
|
||||
/*fprintf (stderr, "%f ", x); */
|
||||
float xx = x * cutoff;
|
||||
#endif
|
||||
if (fabs (x) < 1e-6)
|
||||
return cutoff;
|
||||
else if (fabs (x) > .5 * N)
|
||||
|
@ -376,6 +391,7 @@ cubic_coef (spx_word16_t frac, spx_word16_t interp[4])
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef DOUBLE_PRECISION
|
||||
static int
|
||||
resampler_basic_direct_single (SpeexResamplerState * st,
|
||||
spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
|
||||
|
@ -425,6 +441,7 @@ resampler_basic_direct_single (SpeexResamplerState * st,
|
|||
st->samp_frac_num[channel_index] = samp_frac_num;
|
||||
return out_sample;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#else
|
||||
|
@ -480,6 +497,7 @@ resampler_basic_direct_double (SpeexResamplerState * st,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef DOUBLE_PRECISION
|
||||
static int
|
||||
resampler_basic_interpolate_single (SpeexResamplerState * st,
|
||||
spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len,
|
||||
|
@ -558,6 +576,7 @@ resampler_basic_interpolate_single (SpeexResamplerState * st,
|
|||
st->samp_frac_num[channel_index] = samp_frac_num;
|
||||
return out_sample;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#else
|
||||
|
@ -587,10 +606,16 @@ resampler_basic_interpolate_double (SpeexResamplerState * st,
|
|||
const spx_word16_t frac =
|
||||
PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
|
||||
st->den_rate);
|
||||
#else
|
||||
#ifdef DOUBLE_PRECISION
|
||||
const spx_word16_t frac =
|
||||
((double) ((samp_frac_num * st->oversample) % st->den_rate)) /
|
||||
st->den_rate;
|
||||
#else
|
||||
const spx_word16_t frac =
|
||||
((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
|
||||
st->den_rate;
|
||||
#endif
|
||||
#endif
|
||||
spx_word16_t interp[4];
|
||||
|
||||
|
@ -692,19 +717,26 @@ update_filter (SpeexResamplerState * st)
|
|||
spx_int32_t j;
|
||||
for (j = 0; j < st->filt_len; j++) {
|
||||
st->sinc_table[i * st->filt_len + j] =
|
||||
sinc (st->cutoff,
|
||||
((j - (spx_int32_t) st->filt_len / 2 + 1) -
|
||||
sinc (st->cutoff, ((j - (spx_int32_t) st->filt_len / 2 + 1) -
|
||||
#ifdef DOUBLE_PRECISION
|
||||
((double) i) / st->den_rate), st->filt_len,
|
||||
#else
|
||||
((float) i) / st->den_rate), st->filt_len,
|
||||
#endif
|
||||
quality_map[st->quality].window_func);
|
||||
}
|
||||
}
|
||||
#ifdef FIXED_POINT
|
||||
st->resampler_ptr = resampler_basic_direct_single;
|
||||
#else
|
||||
#ifdef DOUBLE_PRECISION
|
||||
st->resampler_ptr = resampler_basic_direct_double;
|
||||
#else
|
||||
if (st->quality > 8)
|
||||
st->resampler_ptr = resampler_basic_direct_double;
|
||||
else
|
||||
st->resampler_ptr = resampler_basic_direct_single;
|
||||
#endif
|
||||
#endif
|
||||
/*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */
|
||||
} else {
|
||||
|
@ -721,15 +753,23 @@ update_filter (SpeexResamplerState * st)
|
|||
}
|
||||
for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++)
|
||||
st->sinc_table[i + 4] =
|
||||
#ifdef DOUBLE_PRECISION
|
||||
sinc (st->cutoff, (i / (double) st->oversample - st->filt_len / 2),
|
||||
#else
|
||||
sinc (st->cutoff, (i / (float) st->oversample - st->filt_len / 2),
|
||||
#endif
|
||||
st->filt_len, quality_map[st->quality].window_func);
|
||||
#ifdef FIXED_POINT
|
||||
st->resampler_ptr = resampler_basic_interpolate_single;
|
||||
#else
|
||||
#ifdef DOUBLE_PRECISION
|
||||
st->resampler_ptr = resampler_basic_interpolate_double;
|
||||
#else
|
||||
if (st->quality > 8)
|
||||
st->resampler_ptr = resampler_basic_interpolate_double;
|
||||
else
|
||||
st->resampler_ptr = resampler_basic_interpolate_single;
|
||||
#endif
|
||||
#endif
|
||||
/*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */
|
||||
}
|
||||
|
@ -960,11 +1000,18 @@ speex_resampler_process_int (SpeexResamplerState * st,
|
|||
spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
|
||||
spx_int16_t * out, spx_uint32_t * out_len)
|
||||
#else
|
||||
#ifdef DOUBLE_PRECISION
|
||||
EXPORT int
|
||||
speex_resampler_process_float (SpeexResamplerState * st,
|
||||
spx_uint32_t channel_index, const double *in, spx_uint32_t * in_len,
|
||||
double *out, spx_uint32_t * out_len)
|
||||
#else
|
||||
EXPORT int
|
||||
speex_resampler_process_float (SpeexResamplerState * st,
|
||||
spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
|
||||
float *out, spx_uint32_t * out_len)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
int j;
|
||||
spx_uint32_t ilen = *in_len;
|
||||
|
@ -1082,9 +1129,16 @@ speex_resampler_process_int (SpeexResamplerState * st,
|
|||
return RESAMPLER_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef DOUBLE_PRECISION
|
||||
EXPORT int
|
||||
speex_resampler_process_interleaved_float (SpeexResamplerState * st,
|
||||
const double *in, spx_uint32_t * in_len, double *out,
|
||||
spx_uint32_t * out_len)
|
||||
#else
|
||||
EXPORT int
|
||||
speex_resampler_process_interleaved_float (SpeexResamplerState * st,
|
||||
const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len)
|
||||
#endif
|
||||
{
|
||||
spx_uint32_t i;
|
||||
int istride_save, ostride_save;
|
||||
|
|
|
@ -162,10 +162,17 @@ extern "C"
|
|||
* @param out Output buffer
|
||||
* @param out_len Size of the output buffer. Returns the number of samples written
|
||||
*/
|
||||
#ifdef DOUBLE_PRECISION
|
||||
int speex_resampler_process_float (SpeexResamplerState * st,
|
||||
spx_uint32_t channel_index,
|
||||
const double *in,
|
||||
spx_uint32_t * in_len, double *out, spx_uint32_t * out_len);
|
||||
#else
|
||||
int speex_resampler_process_float (SpeexResamplerState * st,
|
||||
spx_uint32_t channel_index,
|
||||
const float *in,
|
||||
spx_uint32_t * in_len, float *out, spx_uint32_t * out_len);
|
||||
#endif
|
||||
|
||||
/** Resample an int array. The input and output buffers must *not* overlap.
|
||||
* @param st Resampler state
|
||||
|
@ -191,9 +198,15 @@ extern "C"
|
|||
* @param out_len Size of the output buffer. Returns the number of samples written.
|
||||
* This is all per-channel.
|
||||
*/
|
||||
#ifdef DOUBLE_PRECISION
|
||||
int speex_resampler_process_interleaved_float (SpeexResamplerState * st,
|
||||
const double *in,
|
||||
spx_uint32_t * in_len, double *out, spx_uint32_t * out_len);
|
||||
#else
|
||||
int speex_resampler_process_interleaved_float (SpeexResamplerState * st,
|
||||
const float *in,
|
||||
spx_uint32_t * in_len, float *out, spx_uint32_t * out_len);
|
||||
#endif
|
||||
|
||||
/** Resample an interleaved int array. The input and output buffers must *not* overlap.
|
||||
* @param st Resampler state
|
||||
|
|
25
gst/speexresample/speex_resampler_double.c
Normal file
25
gst/speexresample/speex_resampler_double.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define FLOATING_POINT
|
||||
#define DOUBLE_PRECISION
|
||||
#define OUTSIDE_SPEEX
|
||||
#define RANDOM_PREFIX resample_double
|
||||
|
||||
#include "resample.c"
|
|
@ -39,48 +39,119 @@ enum
|
|||
|
||||
typedef struct SpeexResamplerState_ SpeexResamplerState;
|
||||
|
||||
typedef struct {
|
||||
SpeexResamplerState *(*init) (guint32 nb_channels,
|
||||
guint32 in_rate, guint32 out_rate, gint quality, gint * err);
|
||||
void (*destroy) (SpeexResamplerState * st);
|
||||
int (*process) (SpeexResamplerState *
|
||||
st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
|
||||
int (*set_rate) (SpeexResamplerState * st,
|
||||
guint32 in_rate, guint32 out_rate);
|
||||
void (*get_rate) (SpeexResamplerState * st,
|
||||
guint32 * in_rate, guint32 * out_rate);
|
||||
void (*get_ratio) (SpeexResamplerState * st,
|
||||
guint32 * ratio_num, guint32 * ratio_den);
|
||||
int (*get_input_latency) (SpeexResamplerState * st);
|
||||
int (*set_quality) (SpeexResamplerState * st, gint quality);
|
||||
int (*reset_mem) (SpeexResamplerState * st);
|
||||
int (*skip_zeros) (SpeexResamplerState * st);
|
||||
const char * (*strerror) (gint err);
|
||||
} SpeexResampleFuncs;
|
||||
|
||||
SpeexResamplerState *resample_float_resampler_init (guint32 nb_channels,
|
||||
guint32 in_rate, guint32 out_rate, gint quality, gint * err);
|
||||
SpeexResamplerState *resample_int_resampler_init (guint32 nb_channels,
|
||||
guint32 in_rate, guint32 out_rate, gint quality, gint * err);
|
||||
|
||||
#define resample_resampler_destroy resample_int_resampler_destroy
|
||||
void resample_resampler_destroy (SpeexResamplerState * st);
|
||||
|
||||
void resample_float_resampler_destroy (SpeexResamplerState * st);
|
||||
int resample_float_resampler_process_interleaved_float (SpeexResamplerState *
|
||||
st, const gfloat * in, guint32 * in_len, gfloat * out, guint32 * out_len);
|
||||
int resample_int_resampler_process_interleaved_int (SpeexResamplerState * st,
|
||||
const gint16 * in, guint32 * in_len, gint16 * out, guint32 * out_len);
|
||||
|
||||
st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
|
||||
int resample_float_resampler_set_rate (SpeexResamplerState * st,
|
||||
guint32 in_rate, guint32 out_rate);
|
||||
int resample_int_resampler_set_rate (SpeexResamplerState * st,
|
||||
guint32 in_rate, guint32 out_rate);
|
||||
|
||||
void resample_float_resampler_get_rate (SpeexResamplerState * st,
|
||||
guint32 * in_rate, guint32 * out_rate);
|
||||
void resample_int_resampler_get_rate (SpeexResamplerState * st,
|
||||
guint32 * in_rate, guint32 * out_rate);
|
||||
|
||||
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_set_quality (SpeexResamplerState * st, gint quality);
|
||||
int resample_float_resampler_reset_mem (SpeexResamplerState * st);
|
||||
int resample_float_resampler_skip_zeros (SpeexResamplerState * st);
|
||||
const char * resample_float_resampler_strerror (gint err);
|
||||
|
||||
static const SpeexResampleFuncs float_funcs =
|
||||
{
|
||||
resample_float_resampler_init,
|
||||
resample_float_resampler_destroy,
|
||||
resample_float_resampler_process_interleaved_float,
|
||||
resample_float_resampler_set_rate,
|
||||
resample_float_resampler_get_rate,
|
||||
resample_float_resampler_get_ratio,
|
||||
resample_float_resampler_get_input_latency,
|
||||
resample_float_resampler_set_quality,
|
||||
resample_float_resampler_reset_mem,
|
||||
resample_float_resampler_skip_zeros,
|
||||
resample_float_resampler_strerror
|
||||
};
|
||||
|
||||
SpeexResamplerState *resample_double_resampler_init (guint32 nb_channels,
|
||||
guint32 in_rate, guint32 out_rate, gint quality, 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);
|
||||
int resample_double_resampler_set_rate (SpeexResamplerState * st,
|
||||
guint32 in_rate, guint32 out_rate);
|
||||
void resample_double_resampler_get_rate (SpeexResamplerState * st,
|
||||
guint32 * in_rate, guint32 * out_rate);
|
||||
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_set_quality (SpeexResamplerState * st, gint quality);
|
||||
int resample_double_resampler_reset_mem (SpeexResamplerState * st);
|
||||
int resample_double_resampler_skip_zeros (SpeexResamplerState * st);
|
||||
const char * resample_double_resampler_strerror (gint err);
|
||||
|
||||
static const SpeexResampleFuncs double_funcs =
|
||||
{
|
||||
resample_double_resampler_init,
|
||||
resample_double_resampler_destroy,
|
||||
resample_double_resampler_process_interleaved_float,
|
||||
resample_double_resampler_set_rate,
|
||||
resample_double_resampler_get_rate,
|
||||
resample_double_resampler_get_ratio,
|
||||
resample_double_resampler_get_input_latency,
|
||||
resample_double_resampler_set_quality,
|
||||
resample_double_resampler_reset_mem,
|
||||
resample_double_resampler_skip_zeros,
|
||||
resample_double_resampler_strerror
|
||||
};
|
||||
|
||||
SpeexResamplerState *resample_int_resampler_init (guint32 nb_channels,
|
||||
guint32 in_rate, guint32 out_rate, gint quality, 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);
|
||||
int resample_int_resampler_set_rate (SpeexResamplerState * st,
|
||||
guint32 in_rate, guint32 out_rate);
|
||||
void resample_int_resampler_get_rate (SpeexResamplerState * st,
|
||||
guint32 * in_rate, guint32 * out_rate);
|
||||
void resample_int_resampler_get_ratio (SpeexResamplerState * st,
|
||||
guint32 * ratio_num, guint32 * ratio_den);
|
||||
|
||||
int resample_float_resampler_get_input_latency (SpeexResamplerState * st);
|
||||
int resample_int_resampler_get_input_latency (SpeexResamplerState * st);
|
||||
|
||||
int resample_float_resampler_set_quality (SpeexResamplerState * st,
|
||||
gint quality);
|
||||
int resample_int_resampler_set_quality (SpeexResamplerState * st, gint quality);
|
||||
|
||||
int resample_float_resampler_reset_mem (SpeexResamplerState * st);
|
||||
int resample_int_resampler_reset_mem (SpeexResamplerState * st);
|
||||
|
||||
int resample_float_resampler_skip_zeros (SpeexResamplerState * st);
|
||||
int resample_int_resampler_skip_zeros (SpeexResamplerState * st);
|
||||
const char * resample_int_resampler_strerror (gint err);
|
||||
|
||||
#define resample_resampler_strerror resample_int_resampler_strerror
|
||||
const char *resample_resampler_strerror (gint err);
|
||||
static const SpeexResampleFuncs int_funcs =
|
||||
{
|
||||
resample_int_resampler_init,
|
||||
resample_int_resampler_destroy,
|
||||
resample_int_resampler_process_interleaved_int,
|
||||
resample_int_resampler_set_rate,
|
||||
resample_int_resampler_get_rate,
|
||||
resample_int_resampler_get_ratio,
|
||||
resample_int_resampler_get_input_latency,
|
||||
resample_int_resampler_set_quality,
|
||||
resample_int_resampler_reset_mem,
|
||||
resample_int_resampler_skip_zeros,
|
||||
resample_int_resampler_strerror
|
||||
};
|
||||
|
||||
#endif /* __SPEEX_RESAMPLER_WRAPPER_H__ */
|
||||
|
|
|
@ -32,8 +32,14 @@
|
|||
* get_peer, and then remove references in every test function */
|
||||
static GstPad *mysrcpad, *mysinkpad;
|
||||
|
||||
#define RESAMPLE_CAPS_FLOAT \
|
||||
"audio/x-raw-float, " \
|
||||
"channels = (int) [ 1, MAX ], " \
|
||||
"rate = (int) [ 1, MAX ], " \
|
||||
"endianness = (int) BYTE_ORDER, " \
|
||||
"width = (int) { 32, 64 }"
|
||||
|
||||
#define RESAMPLE_CAPS_TEMPLATE_STRING \
|
||||
#define RESAMPLE_CAPS_INT \
|
||||
"audio/x-raw-int, " \
|
||||
"channels = (int) [ 1, MAX ], " \
|
||||
"rate = (int) [ 1, MAX ], " \
|
||||
|
@ -42,6 +48,10 @@ static GstPad *mysrcpad, *mysinkpad;
|
|||
"depth = (int) 16, " \
|
||||
"signed = (bool) TRUE"
|
||||
|
||||
#define RESAMPLE_CAPS_TEMPLATE_STRING \
|
||||
RESAMPLE_CAPS_FLOAT " ; " \
|
||||
RESAMPLE_CAPS_INT
|
||||
|
||||
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
|
@ -54,7 +64,8 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
|||
);
|
||||
|
||||
static GstElement *
|
||||
setup_speexresample (int channels, int inrate, int outrate)
|
||||
setup_speexresample (int channels, int inrate, int outrate, int width,
|
||||
gboolean fp)
|
||||
{
|
||||
GstElement *speexresample;
|
||||
GstCaps *caps;
|
||||
|
@ -63,10 +74,15 @@ setup_speexresample (int channels, int inrate, int outrate)
|
|||
GST_DEBUG ("setup_speexresample");
|
||||
speexresample = gst_check_setup_element ("speexresample");
|
||||
|
||||
caps = gst_caps_from_string (RESAMPLE_CAPS_TEMPLATE_STRING);
|
||||
if (fp)
|
||||
caps = gst_caps_from_string (RESAMPLE_CAPS_FLOAT);
|
||||
else
|
||||
caps = gst_caps_from_string (RESAMPLE_CAPS_INT);
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
gst_structure_set (structure, "channels", G_TYPE_INT, channels,
|
||||
"rate", G_TYPE_INT, inrate, NULL);
|
||||
"rate", G_TYPE_INT, inrate, "width", G_TYPE_INT, width, NULL);
|
||||
if (!fp)
|
||||
gst_structure_set (structure, "depth", G_TYPE_INT, width, NULL);
|
||||
fail_unless (gst_caps_is_fixed (caps));
|
||||
|
||||
fail_unless (gst_element_set_state (speexresample,
|
||||
|
@ -77,10 +93,15 @@ setup_speexresample (int channels, int inrate, int outrate)
|
|||
gst_pad_set_caps (mysrcpad, caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
caps = gst_caps_from_string (RESAMPLE_CAPS_TEMPLATE_STRING);
|
||||
if (fp)
|
||||
caps = gst_caps_from_string (RESAMPLE_CAPS_FLOAT);
|
||||
else
|
||||
caps = gst_caps_from_string (RESAMPLE_CAPS_INT);
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
gst_structure_set (structure, "channels", G_TYPE_INT, channels,
|
||||
"rate", G_TYPE_INT, outrate, NULL);
|
||||
"rate", G_TYPE_INT, outrate, "width", G_TYPE_INT, width, NULL);
|
||||
if (!fp)
|
||||
gst_structure_set (structure, "depth", G_TYPE_INT, width, NULL);
|
||||
fail_unless (gst_caps_is_fixed (caps));
|
||||
|
||||
mysinkpad = gst_check_setup_sink_pad (speexresample, &sinktemplate, caps);
|
||||
|
@ -157,7 +178,7 @@ test_perfect_stream_instance (int inrate, int outrate, int samples,
|
|||
int i, j;
|
||||
gint16 *p;
|
||||
|
||||
speexresample = setup_speexresample (2, inrate, outrate);
|
||||
speexresample = setup_speexresample (2, inrate, outrate, 16, FALSE);
|
||||
caps = gst_pad_get_negotiated_caps (mysrcpad);
|
||||
fail_unless (gst_caps_is_fixed (caps));
|
||||
|
||||
|
@ -212,7 +233,6 @@ GST_START_TEST (test_perfect_stream)
|
|||
{
|
||||
/* integral scalings */
|
||||
test_perfect_stream_instance (48000, 24000, 500, 20);
|
||||
#if 0
|
||||
test_perfect_stream_instance (48000, 12000, 500, 20);
|
||||
test_perfect_stream_instance (12000, 24000, 500, 20);
|
||||
test_perfect_stream_instance (12000, 48000, 500, 20);
|
||||
|
@ -224,7 +244,6 @@ GST_START_TEST (test_perfect_stream)
|
|||
/* wacky scalings */
|
||||
test_perfect_stream_instance (12345, 54321, 500, 20);
|
||||
test_perfect_stream_instance (101, 99, 500, 20);
|
||||
#endif
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
@ -246,7 +265,7 @@ test_discont_stream_instance (int inrate, int outrate, int samples,
|
|||
GST_DEBUG ("inrate:%d outrate:%d samples:%d numbuffers:%d",
|
||||
inrate, outrate, samples, numbuffers);
|
||||
|
||||
speexresample = setup_speexresample (2, inrate, outrate);
|
||||
speexresample = setup_speexresample (2, inrate, outrate, 16, FALSE);
|
||||
caps = gst_pad_get_negotiated_caps (mysrcpad);
|
||||
fail_unless (gst_caps_is_fixed (caps));
|
||||
|
||||
|
@ -332,7 +351,7 @@ GST_START_TEST (test_reuse)
|
|||
GstBuffer *inbuffer;
|
||||
GstCaps *caps;
|
||||
|
||||
speexresample = setup_speexresample (1, 9343, 48000);
|
||||
speexresample = setup_speexresample (1, 9343, 48000, 16, FALSE);
|
||||
caps = gst_pad_get_negotiated_caps (mysrcpad);
|
||||
fail_unless (gst_caps_is_fixed (caps));
|
||||
|
||||
|
@ -525,7 +544,7 @@ GST_START_TEST (test_live_switch)
|
|||
GstEvent *newseg;
|
||||
GstCaps *caps;
|
||||
|
||||
speexresample = setup_speexresample (4, 48000, 48000);
|
||||
speexresample = setup_speexresample (4, 48000, 48000, 16, FALSE);
|
||||
|
||||
/* Let the sinkpad act like something that can only handle things of
|
||||
* rate 48000- and can only allocate buffers for that rate, but if someone
|
||||
|
|
Loading…
Reference in a new issue