summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst/speexresample/Makefile.am3
-rw-r--r--gst/speexresample/arch.h23
-rw-r--r--gst/speexresample/gstspeexresample.c263
-rw-r--r--gst/speexresample/gstspeexresample.h5
-rw-r--r--gst/speexresample/resample.c58
-rw-r--r--gst/speexresample/speex_resampler.h13
-rw-r--r--gst/speexresample/speex_resampler_double.c25
-rw-r--r--gst/speexresample/speex_resampler_wrapper.h125
-rw-r--r--tests/check/elements/speexresample.c43
9 files changed, 370 insertions, 188 deletions
diff --git a/gst/speexresample/Makefile.am b/gst/speexresample/Makefile.am
index 3e0c4924a..f4d1534d5 100644
--- a/gst/speexresample/Makefile.am
+++ b/gst/speexresample/Makefile.am
@@ -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) \
diff --git a/gst/speexresample/arch.h b/gst/speexresample/arch.h
index 168f28bdf..86c9b351e 100644
--- a/gst/speexresample/arch.h
+++ b/gst/speexresample/arch.h
@@ -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)
diff --git a/gst/speexresample/gstspeexresample.c b/gst/speexresample/gstspeexresample.c
index f9b5b0e36..e0dee7dbd 100644
--- a/gst/speexresample/gstspeexresample.c
+++ b/gst/speexresample/gstspeexresample.c
@@ -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_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);
+ resample->funcs->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);
-
- 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);
+ len = resample->funcs->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)
- resampler_latency =
- resample_float_resampler_get_input_latency (resample->state);
- else if (resample->state && !resample->fp)
+ if (resample->state)
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);
diff --git a/gst/speexresample/gstspeexresample.h b/gst/speexresample/gstspeexresample.h
index 7e7a68f65..25be5ca99 100644
--- a/gst/speexresample/gstspeexresample.h
+++ b/gst/speexresample/gstspeexresample.h
@@ -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 {
diff --git a/gst/speexresample/resample.c b/gst/speexresample/resample.c
index ec127aa19..6f172509e 100644
--- a/gst/speexresample/resample.c
+++ b/gst/speexresample/resample.c
@@ -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
@@ -588,10 +607,16 @@ resampler_basic_interpolate_double (SpeexResamplerState * st,
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,20 +717,27 @@ 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 {
spx_int32_t i;
@@ -721,16 +753,24 @@ 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); */
}
st->int_advance = st->num_rate / st->den_rate;
@@ -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;
diff --git a/gst/speexresample/speex_resampler.h b/gst/speexresample/speex_resampler.h
index a00c37c88..4e4a44fff 100644
--- a/gst/speexresample/speex_resampler.h
+++ b/gst/speexresample/speex_resampler.h
@@ -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
diff --git a/gst/speexresample/speex_resampler_double.c b/gst/speexresample/speex_resampler_double.c
new file mode 100644
index 000000000..39e242d81
--- /dev/null
+++ b/gst/speexresample/speex_resampler_double.c
@@ -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"
diff --git a/gst/speexresample/speex_resampler_wrapper.h b/gst/speexresample/speex_resampler_wrapper.h
index 6d7c17d03..6f3fba9b8 100644
--- a/gst/speexresample/speex_resampler_wrapper.h
+++ b/gst/speexresample/speex_resampler_wrapper.h
@@ -39,48 +39,119 @@ enum
typedef struct SpeexResamplerState_ SpeexResamplerState;
-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,
+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;
-#define resample_resampler_destroy resample_int_resampler_destroy
-void resample_resampler_destroy (SpeexResamplerState * st);
-
+SpeexResamplerState *resample_float_resampler_init (guint32 nb_channels,
+ guint32 in_rate, guint32 out_rate, gint quality, gint * err);
+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);
-void resample_int_resampler_get_ratio (SpeexResamplerState * st,
+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);
-int resample_float_resampler_get_input_latency (SpeexResamplerState * st);
-int resample_int_resampler_get_input_latency (SpeexResamplerState * st);
+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
+};
-int resample_float_resampler_set_quality (SpeexResamplerState * st,
- gint quality);
+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_int_resampler_get_input_latency (SpeexResamplerState * st);
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__ */
diff --git a/tests/check/elements/speexresample.c b/tests/check/elements/speexresample.c
index a78ada6d1..e070a2d96 100644
--- a/tests/check/elements/speexresample.c
+++ b/tests/check/elements/speexresample.c
@@ -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