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>
* gst/scaletempo/gstscaletempo.c:

View file

@ -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) \

View file

@ -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)

View file

@ -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);

View file

@ -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 {

View file

@ -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;

View file

@ -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

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 *(*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__ */

View file

@ -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