diff options
Diffstat (limited to 'gst/speexresample')
-rw-r--r-- | gst/speexresample/Makefile.am | 3 | ||||
-rw-r--r-- | gst/speexresample/arch.h | 23 | ||||
-rw-r--r-- | gst/speexresample/gstspeexresample.c | 263 | ||||
-rw-r--r-- | gst/speexresample/gstspeexresample.h | 5 | ||||
-rw-r--r-- | gst/speexresample/resample.c | 58 | ||||
-rw-r--r-- | gst/speexresample/speex_resampler.h | 13 | ||||
-rw-r--r-- | gst/speexresample/speex_resampler_double.c | 25 | ||||
-rw-r--r-- | gst/speexresample/speex_resampler_wrapper.h | 125 |
8 files changed, 339 insertions, 176 deletions
diff --git a/gst/speexresample/Makefile.am b/gst/speexresample/Makefile.am index 3e0c4924..f4d1534d 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 168f28bd..86c9b351 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 f9b5b0e3..e0dee7db 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 7e7a68f6..25be5ca9 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 ec127aa1..6f172509 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 a00c37c8..4e4a44ff 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 00000000..39e242d8 --- /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 6d7c17d0..6f3fba9b 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__ */ |