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:
Sebastian Dröge 2008-10-30 12:43:44 +00:00
parent 51262eeb4c
commit 12766882b5
10 changed files with 393 additions and 188 deletions

View file

@ -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> 2008-10-30 Stefan Kost <ensonic@users.sf.net>
* gst/scaletempo/gstscaletempo.c: * gst/scaletempo/gstscaletempo.c:

View file

@ -3,7 +3,8 @@ plugin_LTLIBRARIES = libgstspeexresample.la
libgstspeexresample_la_SOURCES = \ libgstspeexresample_la_SOURCES = \
gstspeexresample.c \ gstspeexresample.c \
speex_resampler_int.c \ speex_resampler_int.c \
speex_resampler_float.c speex_resampler_float.c \
speex_resampler_double.c
libgstspeexresample_la_CFLAGS = \ libgstspeexresample_la_CFLAGS = \
$(GST_PLUGINS_BASE_CFLAGS) \ $(GST_PLUGINS_BASE_CFLAGS) \

View file

@ -137,6 +137,28 @@ typedef spx_word32_t spx_sig_t;
#else #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_mem_t;
typedef float spx_coef_t; typedef float spx_coef_t;
typedef float spx_lsp_t; typedef float spx_lsp_t;
@ -157,6 +179,7 @@ typedef float spx_word32_t;
#define VERY_LARGE32 1e15f #define VERY_LARGE32 1e15f
#define VERY_LARGE16 1e15f #define VERY_LARGE16 1e15f
#define Q15_ONE ((spx_word16_t)1.f) #define Q15_ONE ((spx_word16_t)1.f)
#endif /* DOUBLE_PRECISION */
#define QCONST16(x,bits) (x) #define QCONST16(x,bits) (x)
#define QCONST32(x,bits) (x) #define QCONST32(x,bits) (x)

View file

@ -60,7 +60,7 @@ GST_STATIC_CAPS ( \
"rate = (int) [ 1, MAX ], " \ "rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, MAX ], " \ "channels = (int) [ 1, MAX ], " \
"endianness = (int) BYTE_ORDER, " \ "endianness = (int) BYTE_ORDER, " \
"width = (int) 32; " \ "width = (int) { 32, 64 }; " \
"audio/x-raw-int, " \ "audio/x-raw-int, " \
"rate = (int) [ 1, MAX ], " \ "rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, MAX ], " \ "channels = (int) [ 1, MAX ], " \
@ -196,10 +196,12 @@ gst_speex_resample_stop (GstBaseTransform * base)
GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base); GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base);
if (resample->state) { if (resample->state) {
resample_resampler_destroy (resample->state); resample->funcs->destroy (resample->state);
resample->state = NULL; resample->state = NULL;
} }
resample->funcs = NULL;
gst_caps_replace (&resample->sinkcaps, NULL); gst_caps_replace (&resample->sinkcaps, NULL);
gst_caps_replace (&resample->srccaps, 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)) if (G_UNLIKELY (!ret))
return FALSE; return FALSE;
*size = gst_util_uint64_scale (width, channels, 8); *size = (width / 8) * channels;
return TRUE; return TRUE;
} }
@ -261,38 +263,47 @@ gst_speex_resample_fixate_caps (GstBaseTransform * base,
gst_structure_fixate_field_nearest_int (s, "rate", rate); 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 * static SpeexResamplerState *
gst_speex_resample_init_state (gint channels, gint inrate, gint outrate, gst_speex_resample_init_state (GstSpeexResample * resample, gint width,
gint quality, gboolean fp) gint channels, gint inrate, gint outrate, gint quality, gboolean fp)
{ {
SpeexResamplerState *ret = NULL; SpeexResamplerState *ret = NULL;
gint err = RESAMPLER_ERR_SUCCESS; gint err = RESAMPLER_ERR_SUCCESS;
const SpeexResampleFuncs *funcs = gst_speex_resample_get_funcs (width, fp);
if (fp) ret = funcs->init (channels, inrate, outrate, quality, &err);
ret =
resample_float_resampler_init (channels, inrate, outrate, quality,
&err);
else
ret =
resample_int_resampler_init (channels, inrate, outrate, quality, &err);
if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) { if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
GST_ERROR ("Failed to create resampler state: %s", GST_ERROR_OBJECT (resample, "Failed to create resampler state: %s",
resample_resampler_strerror (err)); funcs->strerror (err));
return NULL; return NULL;
} }
if (fp) funcs->skip_zeros (ret);
resample_float_resampler_skip_zeros (ret);
else
resample_int_resampler_skip_zeros (ret);
return ret; return ret;
} }
static gboolean static gboolean
gst_speex_resample_update_state (GstSpeexResample * resample, gint channels, gst_speex_resample_update_state (GstSpeexResample * resample, gint width,
gint inrate, gint outrate, gint quality, gboolean fp) gint channels, gint inrate, gint outrate, gint quality, gboolean fp)
{ {
gboolean ret = TRUE; gboolean ret = TRUE;
gboolean updated_latency = FALSE; gboolean updated_latency = FALSE;
@ -302,41 +313,38 @@ gst_speex_resample_update_state (GstSpeexResample * resample, gint channels,
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
resample_resampler_destroy (resample->state); || width != resample->width) {
resample->funcs->destroy (resample->state);
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); ret = (resample->state != NULL);
} else if (resample->inrate != inrate || resample->outrate != outrate) { } else if (resample->inrate != inrate || resample->outrate != outrate) {
gint err = RESAMPLER_ERR_SUCCESS; gint err = RESAMPLER_ERR_SUCCESS;
if (fp) err = resample->funcs->set_rate (resample->state, inrate, outrate);
err =
resample_float_resampler_set_rate (resample->state, inrate, outrate);
else
err = resample_int_resampler_set_rate (resample->state, inrate, outrate);
if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS))
GST_ERROR_OBJECT (resample, "Failed to update rate: %s", GST_ERROR_OBJECT (resample, "Failed to update rate: %s",
resample_resampler_strerror (err)); resample->funcs->strerror (err));
ret = (err == RESAMPLER_ERR_SUCCESS); ret = (err == RESAMPLER_ERR_SUCCESS);
} else if (quality != resample->quality) { } else if (quality != resample->quality) {
gint err = RESAMPLER_ERR_SUCCESS; gint err = RESAMPLER_ERR_SUCCESS;
if (fp) err = resample->funcs->set_quality (resample->state, quality);
err = resample_float_resampler_set_quality (resample->state, quality);
else
err = resample_int_resampler_set_quality (resample->state, quality);
if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS))
GST_ERROR_OBJECT (resample, "Failed to update quality: %s", GST_ERROR_OBJECT (resample, "Failed to update quality: %s",
resample_resampler_strerror (err)); resample->funcs->strerror (err));
ret = (err == RESAMPLER_ERR_SUCCESS); ret = (err == RESAMPLER_ERR_SUCCESS);
} }
resample->width = width;
resample->channels = channels; resample->channels = channels;
resample->fp = fp; resample->fp = fp;
resample->quality = quality; resample->quality = quality;
@ -353,20 +361,18 @@ gst_speex_resample_update_state (GstSpeexResample * resample, gint channels,
static void static void
gst_speex_resample_reset_state (GstSpeexResample * resample) gst_speex_resample_reset_state (GstSpeexResample * resample)
{ {
if (resample->state && resample->fp) if (resample->state)
resample_float_resampler_reset_mem (resample->state); resample->funcs->reset_mem (resample->state);
else if (resample->state && !resample->fp)
resample_int_resampler_reset_mem (resample->state);
} }
static gboolean static gboolean
gst_speex_resample_parse_caps (GstCaps * incaps, gst_speex_resample_parse_caps (GstCaps * incaps,
GstCaps * outcaps, gint * channels, gint * inrate, gint * outrate, GstCaps * outcaps, gint * width, gint * channels, gint * inrate,
gboolean * fp) gint * outrate, gboolean * fp)
{ {
GstStructure *structure; GstStructure *structure;
gboolean ret; gboolean ret;
gint myinrate, myoutrate, mychannels; gint mywidth, myinrate, myoutrate, mychannels;
gboolean myfp; gboolean myfp;
GST_DEBUG ("incaps %" GST_PTR_FORMAT ", outcaps %" 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, "rate", &myinrate);
ret &= gst_structure_get_int (structure, "channels", &mychannels); ret &= gst_structure_get_int (structure, "channels", &mychannels);
ret &= gst_structure_get_int (structure, "width", &mywidth);
if (G_UNLIKELY (!ret)) if (G_UNLIKELY (!ret))
goto no_in_rate_channels; goto no_in_rate_channels;
@ -395,7 +402,8 @@ gst_speex_resample_parse_caps (GstCaps * incaps,
*inrate = myinrate; *inrate = myinrate;
if (outrate) if (outrate)
*outrate = myoutrate; *outrate = myoutrate;
if (width)
*width = mywidth;
if (fp) if (fp)
*fp = myfp; *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 static gboolean
gst_speex_resample_transform_size (GstBaseTransform * base, gst_speex_resample_transform_size (GstBaseTransform * base,
GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps, GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps,
guint * othersize) guint * othersize)
{ {
GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base); GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base);
SpeexResamplerState *state;
GstCaps *srccaps, *sinkcaps; GstCaps *srccaps, *sinkcaps;
gboolean use_internal = FALSE; /* whether we use the internal state */
gboolean ret = TRUE; gboolean ret = TRUE;
guint32 ratio_den, ratio_num; 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", GST_LOG_OBJECT (resample, "asked to transform size %d in direction %s",
size, direction == GST_PAD_SINK ? "SINK" : "SRC"); size, direction == GST_PAD_SINK ? "SINK" : "SRC");
@ -437,60 +457,40 @@ gst_speex_resample_transform_size (GstBaseTransform * base,
srccaps = caps; srccaps = caps;
} }
/* if the caps are the ones that _set_caps got called with; we can use ret =
* our own state; otherwise we'll have to create a state */ gst_speex_resample_parse_caps (caps, othercaps, &width, NULL, &inrate,
if (resample->state && gst_caps_is_equal (sinkcaps, resample->sinkcaps) && &outrate, NULL);
gst_caps_is_equal (srccaps, resample->srccaps)) { if (G_UNLIKELY (!ret)) {
use_internal = TRUE; GST_ERROR_OBJECT (resample, "Wrong caps");
state = resample->state; return FALSE;
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;
} }
if (resample->fp || use_internal) gcd = _gcd (inrate, outrate);
resample_float_resampler_get_ratio (state, &ratio_num, &ratio_den); ratio_num = inrate / gcd;
else ratio_den = outrate / gcd;
resample_int_resampler_get_ratio (state, &ratio_num, &ratio_den);
if (direction == GST_PAD_SINK) { if (direction == GST_PAD_SINK) {
gint fac = (fp) ? 4 : 2; gint fac = width / 8;
/* asked to convert size of an incoming buffer */ /* asked to convert size of an incoming buffer */
size /= fac; 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; *othersize *= fac;
size *= fac; size *= fac;
} else { } else {
gint fac = (fp) ? 4 : 2; gint fac = width / 8;
/* asked to convert size of an outgoing buffer */ /* asked to convert size of an outgoing buffer */
size /= fac; 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; *othersize *= fac;
size *= fac; size *= fac;
} }
GST_LOG_OBJECT (resample, "transformed size %d to %d", size, *othersize); GST_LOG_OBJECT (resample, "transformed size %d to %d", size, *othersize);
if (!use_internal)
resample_resampler_destroy (state);
return ret; return ret;
} }
@ -499,22 +499,22 @@ gst_speex_resample_set_caps (GstBaseTransform * base, GstCaps * incaps,
GstCaps * outcaps) GstCaps * outcaps)
{ {
gboolean ret; gboolean ret;
gint inrate = 0, outrate = 0, channels = 0; gint width = 0, inrate = 0, outrate = 0, channels = 0;
gboolean fp = FALSE; gboolean fp;
GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base); GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base);
GST_LOG ("incaps %" GST_PTR_FORMAT ", outcaps %" GST_LOG ("incaps %" GST_PTR_FORMAT ", outcaps %"
GST_PTR_FORMAT, incaps, outcaps); GST_PTR_FORMAT, incaps, outcaps);
ret = gst_speex_resample_parse_caps (incaps, outcaps, ret = gst_speex_resample_parse_caps (incaps, outcaps,
&channels, &inrate, &outrate, &fp); &width, &channels, &inrate, &outrate, &fp);
if (G_UNLIKELY (!ret)) if (G_UNLIKELY (!ret))
return FALSE; return FALSE;
ret = ret =
gst_speex_resample_update_state (resample, channels, inrate, outrate, gst_speex_resample_update_state (resample, width, channels, inrate,
resample->quality, fp); outrate, resample->quality, fp);
if (G_UNLIKELY (!ret)) if (G_UNLIKELY (!ret))
return FALSE; return FALSE;
@ -536,27 +536,16 @@ gst_speex_resample_push_drain (GstSpeexResample * resample)
gint outsize; gint outsize;
guint out_len, out_processed; guint out_len, out_processed;
gint err; gint err;
guint num, den, len;
if (!resample->state) if (!resample->state)
return; return;
if (resample->fp) { resample->funcs->get_ratio (resample->state, &num, &den);
guint num, den;
resample_float_resampler_get_ratio (resample->state, &num, &den); out_len = resample->funcs->get_input_latency (resample->state);
out_len = out_processed = (out_len * den + (num >> 1)) / num;
out_len = resample_float_resampler_get_input_latency (resample->state); outsize = (resample->width / 8) * out_len * resample->channels;
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;
}
res = res =
gst_pad_alloc_buffer_and_set_caps (trans->srcpad, GST_BUFFER_OFFSET_NONE, 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; return;
} }
if (resample->fp) { len = resample->funcs->get_input_latency (resample->state);
guint len = resample_float_resampler_get_input_latency (resample->state);
err = err =
resample_float_resampler_process_interleaved_float (resample->state, resample->funcs->process (resample->state,
NULL, &len, (gfloat *) GST_BUFFER_DATA (buf), &out_processed); NULL, &len, (guint8 *) 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);
}
if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) { if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
GST_WARNING_OBJECT (resample, "Failed to process drain: %s", GST_WARNING_OBJECT (resample, "Failed to process drain: %s",
resample_resampler_strerror (err)); resample->funcs->strerror (err));
gst_buffer_unref (buf); gst_buffer_unref (buf);
return; return;
} }
@ -598,7 +579,7 @@ gst_speex_resample_push_drain (GstSpeexResample * resample)
GST_BUFFER_DURATION (buf) = GST_BUFFER_DURATION (buf) =
GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate); GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate);
GST_BUFFER_SIZE (buf) = 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)) { if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
GST_BUFFER_OFFSET (buf) = resample->next_offset; 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; in_len = GST_BUFFER_SIZE (inbuf) / resample->channels;
out_len = GST_BUFFER_SIZE (outbuf) / resample->channels; out_len = GST_BUFFER_SIZE (outbuf) / resample->channels;
if (resample->fp) { in_len /= (resample->width / 8);
in_len /= 4; out_len /= (resample->width / 8);
out_len /= 4;
} else {
in_len /= 2;
out_len /= 2;
}
in_processed = in_len; in_processed = in_len;
out_processed = out_len; out_processed = out_len;
if (resample->fp) err = resample->funcs->process (resample->state,
err = resample_float_resampler_process_interleaved_float (resample->state, (const guint8 *) GST_BUFFER_DATA (inbuf), &in_processed,
(const gfloat *) GST_BUFFER_DATA (inbuf), &in_processed, (guint8 *) GST_BUFFER_DATA (outbuf), &out_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);
if (G_UNLIKELY (in_len != in_processed)) if (G_UNLIKELY (in_len != in_processed))
GST_WARNING_OBJECT (resample, "Converted %d of %d input samples", 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)) { if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
GST_ERROR_OBJECT (resample, "Failed to convert data: %s", GST_ERROR_OBJECT (resample, "Failed to convert data: %s",
resample_resampler_strerror (err)); resample->funcs->strerror (err));
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} else { } else {
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (outbuf) =
GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate); GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate);
GST_BUFFER_SIZE (outbuf) = 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)) { if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
GST_BUFFER_TIMESTAMP (outbuf) = 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; guint outsamples, insamples;
GstFlowReturn ret; GstFlowReturn ret;
if (resample->state == NULL) if (resample->state == NULL) {
if (G_UNLIKELY (!(resample->state = if (G_UNLIKELY (!(resample->state =
gst_speex_resample_init_state (resample->channels, gst_speex_resample_init_state (resample, resample->width,
resample->inrate, resample->outrate, resample->quality, resample->channels, resample->inrate, resample->outrate,
resample->fp)))) resample->quality, resample->fp))))
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
resample->funcs =
gst_speex_resample_get_funcs (resample->width, resample->fp);
}
data = GST_BUFFER_DATA (inbuf); data = GST_BUFFER_DATA (inbuf);
size = GST_BUFFER_SIZE (inbuf); size = GST_BUFFER_SIZE (inbuf);
timestamp = GST_BUFFER_TIMESTAMP (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 = GST_BUFFER_SIZE (inbuf) / resample->channels;
insamples /= (resample->fp) ? 4 : 2; insamples /= (resample->width / 8);
outsamples = GST_BUFFER_SIZE (outbuf) / resample->channels; outsamples = GST_BUFFER_SIZE (outbuf) / resample->channels;
outsamples /= (resample->fp) ? 4 : 2; outsamples /= (resample->width / 8);
if (GST_CLOCK_TIME_IS_VALID (timestamp) if (GST_CLOCK_TIME_IS_VALID (timestamp)
&& !GST_CLOCK_TIME_IS_VALID (resample->next_ts)) { && !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 rate = resample->inrate;
gint resampler_latency; gint resampler_latency;
if (resample->state && resample->fp) if (resample->state)
resampler_latency = resampler_latency =
resample_float_resampler_get_input_latency (resample->state); resample->funcs->get_input_latency (resample->state);
else if (resample->state && !resample->fp)
resampler_latency =
resample_int_resampler_get_input_latency (resample->state);
else else
resampler_latency = 0; resampler_latency = 0;
@ -936,8 +908,9 @@ gst_speex_resample_set_property (GObject * object, guint prop_id,
resample->quality = g_value_get_int (value); resample->quality = g_value_get_int (value);
GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality); GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality);
gst_speex_resample_update_state (resample, resample->channels, gst_speex_resample_update_state (resample, resample->width,
resample->inrate, resample->outrate, resample->quality, resample->fp); resample->channels, resample->inrate, resample->outrate,
resample->quality, resample->fp);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);

View file

@ -24,6 +24,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/base/gstbasetransform.h> #include <gst/base/gstbasetransform.h>
#include <gst/audio/audio.h>
#include "speex_resampler_wrapper.h" #include "speex_resampler_wrapper.h"
@ -61,13 +62,15 @@ struct _GstSpeexResample {
GstClockTime next_ts; GstClockTime next_ts;
GstClockTime next_upstream_ts; GstClockTime next_upstream_ts;
gboolean fp;
gint channels; gint channels;
gint inrate; gint inrate;
gint outrate; gint outrate;
gint quality; gint quality;
gint width;
gboolean fp;
SpeexResamplerState *state; SpeexResamplerState *state;
const SpeexResampleFuncs *funcs;
}; };
struct _GstSpeexResampleClass { struct _GstSpeexResampleClass {

View file

@ -267,10 +267,17 @@ static const struct QualityMapping quality_map[11] = {
}; };
/*8,24,40,56,80,104,128,160,200,256,320*/ /*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 static double
compute_func (float x, struct FuncDef *func) compute_func (float x, struct FuncDef *func)
{ {
float y, frac; float y, frac;
#endif
double interp[4]; double interp[4];
int ind; int ind;
y = x * func->oversample; y = x * func->oversample;
@ -321,11 +328,19 @@ sinc (float cutoff, float x, int N, struct FuncDef *window_func)
} }
#else #else
/* The slow way of computing a sinc for the table. Should improve that some day */ /* 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 static spx_word16_t
sinc (float cutoff, float x, int N, struct FuncDef *window_func) sinc (float cutoff, float x, int N, struct FuncDef *window_func)
{ {
/*fprintf (stderr, "%f ", x); */ /*fprintf (stderr, "%f ", x); */
float xx = x * cutoff; float xx = x * cutoff;
#endif
if (fabs (x) < 1e-6) if (fabs (x) < 1e-6)
return cutoff; return cutoff;
else if (fabs (x) > .5 * N) else if (fabs (x) > .5 * N)
@ -376,6 +391,7 @@ cubic_coef (spx_word16_t frac, spx_word16_t interp[4])
} }
#endif #endif
#ifndef DOUBLE_PRECISION
static int static int
resampler_basic_direct_single (SpeexResamplerState * st, resampler_basic_direct_single (SpeexResamplerState * st,
spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, 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; st->samp_frac_num[channel_index] = samp_frac_num;
return out_sample; return out_sample;
} }
#endif
#ifdef FIXED_POINT #ifdef FIXED_POINT
#else #else
@ -480,6 +497,7 @@ resampler_basic_direct_double (SpeexResamplerState * st,
} }
#endif #endif
#ifndef DOUBLE_PRECISION
static int static int
resampler_basic_interpolate_single (SpeexResamplerState * st, resampler_basic_interpolate_single (SpeexResamplerState * st,
spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, 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; st->samp_frac_num[channel_index] = samp_frac_num;
return out_sample; return out_sample;
} }
#endif
#ifdef FIXED_POINT #ifdef FIXED_POINT
#else #else
@ -587,10 +606,16 @@ resampler_basic_interpolate_double (SpeexResamplerState * st,
const spx_word16_t frac = const spx_word16_t frac =
PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15), PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15),
st->den_rate); 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 #else
const spx_word16_t frac = const spx_word16_t frac =
((float) ((samp_frac_num * st->oversample) % st->den_rate)) / ((float) ((samp_frac_num * st->oversample) % st->den_rate)) /
st->den_rate; st->den_rate;
#endif
#endif #endif
spx_word16_t interp[4]; spx_word16_t interp[4];
@ -692,19 +717,26 @@ update_filter (SpeexResamplerState * st)
spx_int32_t j; spx_int32_t j;
for (j = 0; j < st->filt_len; j++) { for (j = 0; j < st->filt_len; j++) {
st->sinc_table[i * st->filt_len + j] = st->sinc_table[i * st->filt_len + j] =
sinc (st->cutoff, sinc (st->cutoff, ((j - (spx_int32_t) st->filt_len / 2 + 1) -
((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, ((float) i) / st->den_rate), st->filt_len,
#endif
quality_map[st->quality].window_func); quality_map[st->quality].window_func);
} }
} }
#ifdef FIXED_POINT #ifdef FIXED_POINT
st->resampler_ptr = resampler_basic_direct_single; st->resampler_ptr = resampler_basic_direct_single;
#else
#ifdef DOUBLE_PRECISION
st->resampler_ptr = resampler_basic_direct_double;
#else #else
if (st->quality > 8) if (st->quality > 8)
st->resampler_ptr = resampler_basic_direct_double; st->resampler_ptr = resampler_basic_direct_double;
else else
st->resampler_ptr = resampler_basic_direct_single; st->resampler_ptr = resampler_basic_direct_single;
#endif
#endif #endif
/*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */ /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */
} else { } else {
@ -721,15 +753,23 @@ update_filter (SpeexResamplerState * st)
} }
for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++) for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++)
st->sinc_table[i + 4] = 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), sinc (st->cutoff, (i / (float) st->oversample - st->filt_len / 2),
#endif
st->filt_len, quality_map[st->quality].window_func); st->filt_len, quality_map[st->quality].window_func);
#ifdef FIXED_POINT #ifdef FIXED_POINT
st->resampler_ptr = resampler_basic_interpolate_single; st->resampler_ptr = resampler_basic_interpolate_single;
#else
#ifdef DOUBLE_PRECISION
st->resampler_ptr = resampler_basic_interpolate_double;
#else #else
if (st->quality > 8) if (st->quality > 8)
st->resampler_ptr = resampler_basic_interpolate_double; st->resampler_ptr = resampler_basic_interpolate_double;
else else
st->resampler_ptr = resampler_basic_interpolate_single; st->resampler_ptr = resampler_basic_interpolate_single;
#endif
#endif #endif
/*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */ /*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_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len,
spx_int16_t * out, spx_uint32_t * out_len) spx_int16_t * out, spx_uint32_t * out_len)
#else #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 EXPORT int
speex_resampler_process_float (SpeexResamplerState * st, speex_resampler_process_float (SpeexResamplerState * st,
spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len, spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len,
float *out, spx_uint32_t * out_len) float *out, spx_uint32_t * out_len)
#endif #endif
#endif
{ {
int j; int j;
spx_uint32_t ilen = *in_len; spx_uint32_t ilen = *in_len;
@ -1082,9 +1129,16 @@ speex_resampler_process_int (SpeexResamplerState * st,
return RESAMPLER_ERR_SUCCESS; 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 EXPORT int
speex_resampler_process_interleaved_float (SpeexResamplerState * st, speex_resampler_process_interleaved_float (SpeexResamplerState * st,
const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len) const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len)
#endif
{ {
spx_uint32_t i; spx_uint32_t i;
int istride_save, ostride_save; int istride_save, ostride_save;

View file

@ -162,10 +162,17 @@ extern "C"
* @param out Output buffer * @param out Output buffer
* @param out_len Size of the output buffer. Returns the number of samples written * @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, int speex_resampler_process_float (SpeexResamplerState * st,
spx_uint32_t channel_index, spx_uint32_t channel_index,
const float *in, const float *in,
spx_uint32_t * in_len, float *out, spx_uint32_t * out_len); 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. /** Resample an int array. The input and output buffers must *not* overlap.
* @param st Resampler state * @param st Resampler state
@ -191,9 +198,15 @@ extern "C"
* @param out_len Size of the output buffer. Returns the number of samples written. * @param out_len Size of the output buffer. Returns the number of samples written.
* This is all per-channel. * 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, int speex_resampler_process_interleaved_float (SpeexResamplerState * st,
const float *in, const float *in,
spx_uint32_t * in_len, float *out, spx_uint32_t * out_len); 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. /** Resample an interleaved int array. The input and output buffers must *not* overlap.
* @param st Resampler state * @param st Resampler state

View 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"

View file

@ -39,48 +39,119 @@ enum
typedef struct SpeexResamplerState_ SpeexResamplerState; 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, 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, gint * err);
SpeexResamplerState *resample_int_resampler_init (guint32 nb_channels, void resample_float_resampler_destroy (SpeexResamplerState * st);
guint32 in_rate, guint32 out_rate, gint quality, gint * err);
#define resample_resampler_destroy resample_int_resampler_destroy
void resample_resampler_destroy (SpeexResamplerState * st);
int resample_float_resampler_process_interleaved_float (SpeexResamplerState * int resample_float_resampler_process_interleaved_float (SpeexResamplerState *
st, const gfloat * in, guint32 * in_len, gfloat * out, guint32 * out_len); st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len);
int resample_int_resampler_process_interleaved_int (SpeexResamplerState * st,
const gint16 * in, guint32 * in_len, gint16 * out, guint32 * out_len);
int resample_float_resampler_set_rate (SpeexResamplerState * st, int resample_float_resampler_set_rate (SpeexResamplerState * st,
guint32 in_rate, guint32 out_rate); 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, void resample_float_resampler_get_rate (SpeexResamplerState * st,
guint32 * in_rate, guint32 * out_rate); 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, 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_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, void resample_int_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_int_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_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_int_resampler_reset_mem (SpeexResamplerState * st);
int resample_float_resampler_skip_zeros (SpeexResamplerState * st);
int resample_int_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 static const SpeexResampleFuncs int_funcs =
const char *resample_resampler_strerror (gint err); {
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__ */ #endif /* __SPEEX_RESAMPLER_WRAPPER_H__ */

View file

@ -32,8 +32,14 @@
* get_peer, and then remove references in every test function */ * get_peer, and then remove references in every test function */
static GstPad *mysrcpad, *mysinkpad; 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, " \ "audio/x-raw-int, " \
"channels = (int) [ 1, MAX ], " \ "channels = (int) [ 1, MAX ], " \
"rate = (int) [ 1, MAX ], " \ "rate = (int) [ 1, MAX ], " \
@ -42,6 +48,10 @@ static GstPad *mysrcpad, *mysinkpad;
"depth = (int) 16, " \ "depth = (int) 16, " \
"signed = (bool) TRUE" "signed = (bool) TRUE"
#define RESAMPLE_CAPS_TEMPLATE_STRING \
RESAMPLE_CAPS_FLOAT " ; " \
RESAMPLE_CAPS_INT
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_SINK,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
@ -54,7 +64,8 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
); );
static GstElement * static GstElement *
setup_speexresample (int channels, int inrate, int outrate) setup_speexresample (int channels, int inrate, int outrate, int width,
gboolean fp)
{ {
GstElement *speexresample; GstElement *speexresample;
GstCaps *caps; GstCaps *caps;
@ -63,10 +74,15 @@ setup_speexresample (int channels, int inrate, int outrate)
GST_DEBUG ("setup_speexresample"); GST_DEBUG ("setup_speexresample");
speexresample = gst_check_setup_element ("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); structure = gst_caps_get_structure (caps, 0);
gst_structure_set (structure, "channels", G_TYPE_INT, channels, 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_caps_is_fixed (caps));
fail_unless (gst_element_set_state (speexresample, 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_pad_set_caps (mysrcpad, caps);
gst_caps_unref (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); structure = gst_caps_get_structure (caps, 0);
gst_structure_set (structure, "channels", G_TYPE_INT, channels, 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)); fail_unless (gst_caps_is_fixed (caps));
mysinkpad = gst_check_setup_sink_pad (speexresample, &sinktemplate, 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; int i, j;
gint16 *p; gint16 *p;
speexresample = setup_speexresample (2, inrate, outrate); speexresample = setup_speexresample (2, inrate, outrate, 16, FALSE);
caps = gst_pad_get_negotiated_caps (mysrcpad); caps = gst_pad_get_negotiated_caps (mysrcpad);
fail_unless (gst_caps_is_fixed (caps)); fail_unless (gst_caps_is_fixed (caps));
@ -212,7 +233,6 @@ GST_START_TEST (test_perfect_stream)
{ {
/* integral scalings */ /* integral scalings */
test_perfect_stream_instance (48000, 24000, 500, 20); test_perfect_stream_instance (48000, 24000, 500, 20);
#if 0
test_perfect_stream_instance (48000, 12000, 500, 20); test_perfect_stream_instance (48000, 12000, 500, 20);
test_perfect_stream_instance (12000, 24000, 500, 20); test_perfect_stream_instance (12000, 24000, 500, 20);
test_perfect_stream_instance (12000, 48000, 500, 20); test_perfect_stream_instance (12000, 48000, 500, 20);
@ -224,7 +244,6 @@ GST_START_TEST (test_perfect_stream)
/* wacky scalings */ /* wacky scalings */
test_perfect_stream_instance (12345, 54321, 500, 20); test_perfect_stream_instance (12345, 54321, 500, 20);
test_perfect_stream_instance (101, 99, 500, 20); test_perfect_stream_instance (101, 99, 500, 20);
#endif
} }
GST_END_TEST; 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", GST_DEBUG ("inrate:%d outrate:%d samples:%d numbuffers:%d",
inrate, outrate, samples, numbuffers); 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); caps = gst_pad_get_negotiated_caps (mysrcpad);
fail_unless (gst_caps_is_fixed (caps)); fail_unless (gst_caps_is_fixed (caps));
@ -332,7 +351,7 @@ GST_START_TEST (test_reuse)
GstBuffer *inbuffer; GstBuffer *inbuffer;
GstCaps *caps; GstCaps *caps;
speexresample = setup_speexresample (1, 9343, 48000); speexresample = setup_speexresample (1, 9343, 48000, 16, FALSE);
caps = gst_pad_get_negotiated_caps (mysrcpad); caps = gst_pad_get_negotiated_caps (mysrcpad);
fail_unless (gst_caps_is_fixed (caps)); fail_unless (gst_caps_is_fixed (caps));
@ -525,7 +544,7 @@ GST_START_TEST (test_live_switch)
GstEvent *newseg; GstEvent *newseg;
GstCaps *caps; 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 /* 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 * rate 48000- and can only allocate buffers for that rate, but if someone