mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-18 07:47:17 +00:00
684cf44ee3
when downsampling, the output buffer can be filled before all the input samples are consumed. this is correct: when downsampling, several input samples are needed for each output sample, so when only a small number of input samples are available the number of output samples produced can be 0. the resampler, however, was discarding those extra input samples instead of clocking them into its filter history for the next iteration. this patch fixes this by removing the check that the output buffer is full. the code now always loops until all input samples are consumed, and relies on the calling code to have provided a suitably sized location for the output. note that there are already other checks in place in the calling code to ensure that this is the case. https://bugzilla.gnome.org/show_bug.cgi?id=732908 |
||
---|---|---|
.. | ||
arch.h | ||
fixed_arm4.h | ||
fixed_arm5e.h | ||
fixed_bfin.h | ||
fixed_debug.h | ||
fixed_generic.h | ||
gstaudioresample.c | ||
gstaudioresample.h | ||
Makefile.am | ||
README | ||
resample.c | ||
resample_neon.h | ||
resample_sse.h | ||
speex_resampler.h | ||
speex_resampler_double.c | ||
speex_resampler_float.c | ||
speex_resampler_int.c | ||
speex_resampler_wrapper.h |
arch.h fixed_arm4.h fixed_arm5e.h fixed_bfin.h fixed_debug.h fixed_generic.h resample.c speex_resampler.h are taken from http://git.xiph.org/speex.git/ as of 2009-11-10. The only changes are: diff -Naur old/arch.h new/arch.h --- old/arch.h 2009-11-10 12:18:29.000000000 +0100 +++ new/arch.h 2009-11-10 12:19:09.000000000 +0100 @@ -78,7 +78,10 @@ #include "../include/speex/speex_types.h" #endif +#ifndef ABS #define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */ +#endif + #define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */ #define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */ #define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */ @@ -134,6 +137,28 @@ #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; @@ -154,6 +179,7 @@ #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 -Naur old/resample.c new/resample.c --- old/resample.c 2009-11-10 12:18:51.000000000 +0100 +++ new/resample.c 2009-11-10 12:19:09.000000000 +0100 @@ -63,22 +63,27 @@ #ifdef OUTSIDE_SPEEX #include <stdlib.h> -static void * + +#include <glib.h> + +#define EXPORT G_GNUC_INTERNAL + +static inline void * speex_alloc (int size) { - return calloc (size, 1); + return g_malloc0 (size); } -static void * +static inline void * speex_realloc (void *ptr, int size) { - return realloc (ptr, size); + return g_realloc (ptr, size); } -static void +static inline void speex_free (void *ptr) { - free (ptr); + g_free (ptr); } #include "speex_resampler.h" @@ -90,7 +95,6 @@ #include "os_support.h" #endif /* OUTSIDE_SPEEX */ -#include "stack_alloc.h" #include <math.h> #ifndef M_PI @@ -263,10 +267,17 @@ }; /*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; @@ -317,11 +328,19 @@ } #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) @@ -372,6 +391,7 @@ } #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, @@ -428,6 +448,7 @@ st->samp_frac_num[channel_index] = samp_frac_num; return out_sample; } +#endif #ifdef FIXED_POINT #else @@ -483,6 +504,7 @@ } #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, @@ -562,6 +584,7 @@ st->samp_frac_num[channel_index] = samp_frac_num; return out_sample; } +#endif #ifdef FIXED_POINT #else @@ -592,10 +615,16 @@ 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]; @@ -696,20 +725,27 @@ 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; @@ -725,16 +761,24 @@ } 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; @@ -964,11 +1008,18 @@ 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; @@ -1086,9 +1137,16 @@ 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 -Naur old/speex_resampler.h new/speex_resampler.h --- old/speex_resampler.h 2009-11-10 12:18:09.000000000 +0100 +++ new/speex_resampler.h 2009-11-10 12:19:09.000000000 +0100 @@ -77,10 +77,10 @@ #define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem) #define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror) -#define spx_int16_t short -#define spx_int32_t int -#define spx_uint16_t unsigned short -#define spx_uint32_t unsigned int +#define spx_int16_t gint16 +#define spx_int32_t gint32 +#define spx_uint16_t guint16 +#define spx_uint32_t guint32 #else /* OUTSIDE_SPEEX */ @@ -166,12 +166,21 @@ * @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 @@ -199,11 +208,19 @@ * @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