diff options
author | Sebastian Dröge <slomo@circular-chaos.org> | 2008-11-27 19:22:42 +0000 |
---|---|---|
committer | Sebastian Dröge <slomo@circular-chaos.org> | 2008-11-27 19:22:42 +0000 |
commit | d56af9d36dabd5339be7ec71d32d2edf536ca832 (patch) | |
tree | 32483c2cca147e14d5df55c99f274ea29d5130ab /gst | |
parent | bf2d02c1b6a78cf7bf117fb4fa5c909218863824 (diff) | |
download | gst-plugins-bad-d56af9d36dabd5339be7ec71d32d2edf536ca832.tar.gz gst-plugins-bad-d56af9d36dabd5339be7ec71d32d2edf536ca832.tar.bz2 gst-plugins-bad-d56af9d36dabd5339be7ec71d32d2edf536ca832.zip |
Remove old speexresample files.
Original commit message from CVS:
* gst/speexresample/Makefile.am:
* gst/speexresample/README:
* gst/speexresample/arch.h:
* gst/speexresample/fixed_arm4.h:
* gst/speexresample/fixed_arm5e.h:
* gst/speexresample/fixed_bfin.h:
* gst/speexresample/fixed_debug.h:
* gst/speexresample/fixed_generic.h:
* gst/speexresample/gstspeexresample.c:
* gst/speexresample/gstspeexresample.h:
* gst/speexresample/resample.c:
* gst/speexresample/resample_sse.h:
* gst/speexresample/speex_resampler.h:
* gst/speexresample/speex_resampler_double.c:
* gst/speexresample/speex_resampler_float.c:
* gst/speexresample/speex_resampler_int.c:
* gst/speexresample/speex_resampler_wrapper.h:
* tests/check/elements/speexresample.c:
Remove old speexresample files.
Diffstat (limited to 'gst')
-rw-r--r-- | gst/speexresample/Makefile.am | 17 | ||||
-rw-r--r-- | gst/speexresample/README | 87 | ||||
-rw-r--r-- | gst/speexresample/arch.h | 36 | ||||
-rw-r--r-- | gst/speexresample/fixed_arm4.h | 130 | ||||
-rw-r--r-- | gst/speexresample/fixed_arm5e.h | 166 | ||||
-rw-r--r-- | gst/speexresample/fixed_bfin.h | 134 | ||||
-rw-r--r-- | gst/speexresample/fixed_debug.h | 525 | ||||
-rw-r--r-- | gst/speexresample/fixed_generic.h | 4 | ||||
-rw-r--r-- | gst/speexresample/gstspeexresample.c | 1023 | ||||
-rw-r--r-- | gst/speexresample/gstspeexresample.h | 24 | ||||
-rw-r--r-- | gst/speexresample/resample.c | 784 | ||||
-rw-r--r-- | gst/speexresample/resample_sse.h | 128 | ||||
-rw-r--r-- | gst/speexresample/speex_resampler.h | 162 | ||||
-rw-r--r-- | gst/speexresample/speex_resampler_double.c | 25 | ||||
-rw-r--r-- | gst/speexresample/speex_resampler_float.c | 2 | ||||
-rw-r--r-- | gst/speexresample/speex_resampler_int.c | 2 | ||||
-rw-r--r-- | gst/speexresample/speex_resampler_wrapper.h | 131 |
17 files changed, 887 insertions, 2493 deletions
diff --git a/gst/speexresample/Makefile.am b/gst/speexresample/Makefile.am index 93a26116..3e0c4924 100644 --- a/gst/speexresample/Makefile.am +++ b/gst/speexresample/Makefile.am @@ -3,36 +3,29 @@ plugin_LTLIBRARIES = libgstspeexresample.la libgstspeexresample_la_SOURCES = \ gstspeexresample.c \ speex_resampler_int.c \ - speex_resampler_float.c \ - speex_resampler_double.c + speex_resampler_float.c libgstspeexresample_la_CFLAGS = \ $(GST_PLUGINS_BASE_CFLAGS) \ $(GST_BASE_CFLAGS) \ - $(GST_CFLAGS) \ - $(LIBOIL_CFLAGS) + $(GST_CFLAGS) libgstspeexresample_la_LIBADD = \ $(GST_PLUGINS_BASE_LIBS) \ $(GST_BASE_LIBS) \ $(GST_LIBS) \ -lgstaudio-$(GST_MAJORMINOR) \ - $(LIBOIL_LIBS) \ $(LIBM) libgstspeexresample_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstspeexresample_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = \ arch.h \ - fixed_arm4.h \ - fixed_arm5e.h \ - fixed_bfin.h \ - fixed_debug.h \ fixed_generic.h \ gstspeexresample.h \ - resample.c \ - resample_sse.h \ speex_resampler.h \ speex_resampler_wrapper.h +EXTRA_DIST = \ + resample.c + diff --git a/gst/speexresample/README b/gst/speexresample/README index 79e11b32..68d8c290 100644 --- a/gst/speexresample/README +++ b/gst/speexresample/README @@ -1,48 +1,66 @@ - arch.h - fixed_arm4.h - fixed_arm5e.h - fixed_bfin.h - fixed_debug.h - fixed_generic.h - resample.c - speex_resampler.h +resample.c +arch.h +fixed_generic.h +speex_resampler.h -are taken from http://git.xiph.org/speex.git/ as of 2008-10-28. +are taken from http://svn.xiph.org/trunk/speex/ revision 14232. The only changes are: ---- arch.h 2008-10-28 12:21:37.000000000 +0100 -+++ arch.h 2008-10-28 12:27:56.000000000 +0100 -@@ -78,7 +78,10 @@ - #include "../include/speex/speex_types.h" +--- speex/libspeex/arch.h 2007-11-21 11:05:46.000000000 +0100 ++++ speexresample/arch.h 2007-11-20 05:41:09.000000000 +0100 +@@ -78,7 +78,9 @@ + #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. */ ---- resample.c 2008-10-28 12:21:35.000000000 +0100 -+++ resample.c 2008-10-28 12:33:46.000000000 +0100 -@@ -63,22 +63,27 @@ + +--- speex/include/speex/speex_resampler.h 2007-11-21 11:05:44.000000000 +0100 ++++ speexresample/speex_resampler.h 2007-11-21 11:10:02.000000000 +0100 +@@ -41,6 +41,8 @@ + + #ifdef OUTSIDE_SPEEX + ++#include <glib.h> ++ + /********* WARNING: MENTAL SANITY ENDS HERE *************/ + + /* If the resampler is defined outside of Speex, we change the symbol names so that +@@ -75,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 */ + +--- speex/libspeex/resample.c 2007-11-25 14:15:38.000000000 +0100 ++++ speexresample/resample.c 2007-11-25 14:15:31.000000000 +0100 +@@ -62,20 +62,23 @@ #ifdef OUTSIDE_SPEEX #include <stdlib.h> -static void * -+ +#include <glib.h> + -+#define EXPORT -+ +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) @@ -50,8 +68,8 @@ The only changes are: - return realloc (ptr, size); + return g_realloc (ptr, size); } - -static void ++ +static inline void speex_free (void *ptr) { @@ -60,28 +78,3 @@ The only changes are: } #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 ---- speex_resampler.h 2008-10-28 12:21:37.000000000 +0100 -+++ speex_resampler.h 2008-10-28 12:30:48.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 */ - diff --git a/gst/speexresample/arch.h b/gst/speexresample/arch.h index 86c9b351..3b341f0a 100644 --- a/gst/speexresample/arch.h +++ b/gst/speexresample/arch.h @@ -40,7 +40,7 @@ #define SPEEX_MINOR_VERSION 1 /**< Minor Speex version. */ #define SPEEX_MICRO_VERSION 15 /**< Micro Speex version. */ #define SPEEX_EXTRA_VERSION "" /**< Extra Speex version. */ -#define SPEEX_VERSION "speex-1.2beta3" /**< Speex version string. */ +#define SPEEX_VERSION "speex-1.2beta4" /**< Speex version string. */ #endif /* A couple test to catch stupid option combinations */ @@ -75,13 +75,12 @@ #endif #ifndef OUTSIDE_SPEEX -#include "../include/speex/speex_types.h" +#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. */ @@ -92,7 +91,7 @@ #ifdef FIXED_POINT typedef spx_int16_t spx_word16_t; -typedef spx_int32_t spx_word32_t; +typedef spx_int32_t spx_word32_t; typedef spx_word32_t spx_mem_t; typedef spx_word16_t spx_coef_t; typedef spx_word16_t spx_lsp_t; @@ -137,28 +136,6 @@ 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; @@ -179,7 +156,6 @@ 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) @@ -243,11 +219,11 @@ typedef float spx_word32_t; #if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) /* 2 on TI C5x DSP */ -#define BYTES_PER_CHAR 2 +#define BYTES_PER_CHAR 2 #define BITS_PER_CHAR 16 #define LOG2_BITS_PER_CHAR 4 -#else +#else #define BYTES_PER_CHAR 1 #define BITS_PER_CHAR 8 @@ -258,7 +234,7 @@ typedef float spx_word32_t; #ifdef FIXED_DEBUG -extern long long spx_mips; +long long spx_mips=0; #endif diff --git a/gst/speexresample/fixed_arm4.h b/gst/speexresample/fixed_arm4.h deleted file mode 100644 index df99a60f..00000000 --- a/gst/speexresample/fixed_arm4.h +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright (C) 2004 Jean-Marc Valin */ -/** - @file fixed_arm4.h - @brief ARM4 fixed-point operations -*/ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Neither the name of the Xiph.org Foundation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef FIXED_ARM4_H -#define FIXED_ARM4_H - -#undef MULT16_32_Q14 -static inline spx_word32_t -MULT16_32_Q14 (spx_word16_t x, spx_word32_t y) -{ - int res; - int dummy; -asm ("smull %0,%1,%2,%3 \n\t" "mov %0, %0, lsr #14 \n\t" "add %0, %0, %1, lsl #18 \n\t":"=&r" (res), - "=&r" - (dummy) -: "r" (y), "r" ((int) x)); - return (res); -} - -#undef MULT16_32_Q15 -static inline spx_word32_t -MULT16_32_Q15 (spx_word16_t x, spx_word32_t y) -{ - int res; - int dummy; -asm ("smull %0,%1,%2,%3 \n\t" "mov %0, %0, lsr #15 \n\t" "add %0, %0, %1, lsl #17 \n\t":"=&r" (res), - "=&r" - (dummy) -: "r" (y), "r" ((int) x)); - return (res); -} - -#undef DIV32_16 -static inline short -DIV32_16 (int a, int b) -{ - int res = 0; - int dead1, dead2, dead3, dead4, dead5; - __asm__ __volatile__ ("\teor %5, %0, %1\n" - "\tmovs %4, %0\n" - "\trsbmi %0, %0, #0 \n" - "\tmovs %4, %1\n" - "\trsbmi %1, %1, #0 \n" - "\tmov %4, #1\n" - "\tsubs %3, %0, %1, asl #14 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #14 \n" - "\tsubs %3, %0, %1, asl #13 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #13 \n" - "\tsubs %3, %0, %1, asl #12 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #12 \n" - "\tsubs %3, %0, %1, asl #11 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #11 \n" - "\tsubs %3, %0, %1, asl #10 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #10 \n" - "\tsubs %3, %0, %1, asl #9 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #9 \n" - "\tsubs %3, %0, %1, asl #8 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #8 \n" - "\tsubs %3, %0, %1, asl #7 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #7 \n" - "\tsubs %3, %0, %1, asl #6 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #6 \n" - "\tsubs %3, %0, %1, asl #5 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #5 \n" - "\tsubs %3, %0, %1, asl #4 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #4 \n" - "\tsubs %3, %0, %1, asl #3 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #3 \n" - "\tsubs %3, %0, %1, asl #2 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #2 \n" - "\tsubs %3, %0, %1, asl #1 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4, asl #1 \n" - "\tsubs %3, %0, %1 \n" - "\tmovpl %0, %3 \n" - "\torrpl %2, %2, %4 \n" - "\tmovs %5, %5, lsr #31 \n" - "\trsbne %2, %2, #0 \n":"=r" (dead1), "=r" (dead2), "=r" (res), - "=r" (dead3), "=r" (dead4), "=r" (dead5) - :"0" (a), "1" (b), "2" (res) - :"cc"); - return res; -} - - -#endif diff --git a/gst/speexresample/fixed_arm5e.h b/gst/speexresample/fixed_arm5e.h deleted file mode 100644 index c995d54b..00000000 --- a/gst/speexresample/fixed_arm5e.h +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright (C) 2003 Jean-Marc Valin */ -/** - @file fixed_arm5e.h - @brief ARM-tuned fixed-point operations -*/ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Neither the name of the Xiph.org Foundation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef FIXED_ARM5E_H -#define FIXED_ARM5E_H - -#undef MULT16_16 -static inline spx_word32_t -MULT16_16 (spx_word16_t x, spx_word16_t y) -{ - int res; -asm ("smulbb %0,%1,%2;\n":"=&r" (res) -: "%r" (x), "r" (y)); - return (res); -} - -#undef MAC16_16 -static inline spx_word32_t -MAC16_16 (spx_word32_t a, spx_word16_t x, spx_word32_t y) -{ - int res; -asm ("smlabb %0,%1,%2,%3;\n":"=&r" (res) -: "%r" (x), "r" (y), "r" (a)); - return (res); -} - -#undef MULT16_32_Q15 -static inline spx_word32_t -MULT16_32_Q15 (spx_word16_t x, spx_word32_t y) -{ - int res; -asm ("smulwb %0,%1,%2;\n":"=&r" (res) -: "%r" (y << 1), "r" (x)); - return (res); -} - -#undef MAC16_32_Q15 -static inline spx_word32_t -MAC16_32_Q15 (spx_word32_t a, spx_word16_t x, spx_word32_t y) -{ - int res; -asm ("smlawb %0,%1,%2,%3;\n":"=&r" (res) -: "%r" (y << 1), "r" (x), "r" (a)); - return (res); -} - -#undef MULT16_32_Q11 -static inline spx_word32_t -MULT16_32_Q11 (spx_word16_t x, spx_word32_t y) -{ - int res; -asm ("smulwb %0,%1,%2;\n":"=&r" (res) -: "%r" (y << 5), "r" (x)); - return (res); -} - -#undef MAC16_32_Q11 -static inline spx_word32_t -MAC16_32_Q11 (spx_word32_t a, spx_word16_t x, spx_word32_t y) -{ - int res; -asm ("smlawb %0,%1,%2,%3;\n":"=&r" (res) -: "%r" (y << 5), "r" (x), "r" (a)); - return (res); -} - -#undef DIV32_16 -static inline short -DIV32_16 (int a, int b) -{ - int res = 0; - int dead1, dead2, dead3, dead4, dead5; - __asm__ __volatile__ ("\teor %5, %0, %1\n" - "\tmovs %4, %0\n" - "\trsbmi %0, %0, #0 \n" - "\tmovs %4, %1\n" - "\trsbmi %1, %1, #0 \n" - "\tmov %4, #1\n" - "\tsubs %3, %0, %1, asl #14 \n" - "\torrpl %2, %2, %4, asl #14 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #13 \n" - "\torrpl %2, %2, %4, asl #13 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #12 \n" - "\torrpl %2, %2, %4, asl #12 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #11 \n" - "\torrpl %2, %2, %4, asl #11 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #10 \n" - "\torrpl %2, %2, %4, asl #10 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #9 \n" - "\torrpl %2, %2, %4, asl #9 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #8 \n" - "\torrpl %2, %2, %4, asl #8 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #7 \n" - "\torrpl %2, %2, %4, asl #7 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #6 \n" - "\torrpl %2, %2, %4, asl #6 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #5 \n" - "\torrpl %2, %2, %4, asl #5 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #4 \n" - "\torrpl %2, %2, %4, asl #4 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #3 \n" - "\torrpl %2, %2, %4, asl #3 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #2 \n" - "\torrpl %2, %2, %4, asl #2 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1, asl #1 \n" - "\torrpl %2, %2, %4, asl #1 \n" - "\tmovpl %0, %3 \n" - "\tsubs %3, %0, %1 \n" - "\torrpl %2, %2, %4 \n" - "\tmovpl %0, %3 \n" - "\tmovs %5, %5, lsr #31 \n" - "\trsbne %2, %2, #0 \n":"=r" (dead1), "=r" (dead2), "=r" (res), - "=r" (dead3), "=r" (dead4), "=r" (dead5) - :"0" (a), "1" (b), "2" (res) - :"memory", "cc"); - return res; -} - - - - -#endif diff --git a/gst/speexresample/fixed_bfin.h b/gst/speexresample/fixed_bfin.h deleted file mode 100644 index 63b3fb4b..00000000 --- a/gst/speexresample/fixed_bfin.h +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright (C) 2005 Analog Devices - Author: Jean-Marc Valin */ -/** - @file fixed_bfin.h - @brief Blackfin fixed-point operations -*/ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Neither the name of the Xiph.org Foundation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef FIXED_BFIN_H -#define FIXED_BFIN_H - -#undef PDIV32_16 -static inline spx_word16_t -PDIV32_16 (spx_word32_t a, spx_word16_t b) -{ - spx_word32_t res, bb; - bb = b; - a += b >> 1; - __asm__ ("P0 = 15;\n\t" "R0 = %1;\n\t" "R1 = %2;\n\t" - //"R0 = R0 + R1;\n\t" -"R0 <<= 1;\n\t" "DIVS (R0, R1);\n\t" "LOOP divide%= LC0 = P0;\n\t" "LOOP_BEGIN divide%=;\n\t" "DIVQ (R0, R1);\n\t" "LOOP_END divide%=;\n\t" "R0 = R0.L;\n\t" "%0 = R0;\n\t":"=m" - (res) -: "m" (a), "m" (bb) -: "P0", "R0", "R1", "cc"); - return res; -} - -#undef DIV32_16 -static inline spx_word16_t -DIV32_16 (spx_word32_t a, spx_word16_t b) -{ - spx_word32_t res, bb; - bb = b; - /* Make the roundinf consistent with the C version - (do we need to do that?) */ - if (a < 0) - a += (b - 1); -__asm__ ("P0 = 15;\n\t" "R0 = %1;\n\t" "R1 = %2;\n\t" "R0 <<= 1;\n\t" "DIVS (R0, R1);\n\t" "LOOP divide%= LC0 = P0;\n\t" "LOOP_BEGIN divide%=;\n\t" "DIVQ (R0, R1);\n\t" "LOOP_END divide%=;\n\t" "R0 = R0.L;\n\t" "%0 = R0;\n\t":"=m" (res) -: "m" (a), "m" (bb) -: "P0", "R0", "R1", "cc"); - return res; -} - -#undef MAX16 -static inline spx_word16_t -MAX16 (spx_word16_t a, spx_word16_t b) -{ - spx_word32_t res; -__asm__ ("%1 = %1.L (X);\n\t" "%2 = %2.L (X);\n\t" "%0 = MAX(%1,%2);":"=d" (res) -: "%d" (a), "d" (b) - ); - return res; -} - -#undef MULT16_32_Q15 -static inline spx_word32_t -MULT16_32_Q15 (spx_word16_t a, spx_word32_t b) -{ - spx_word32_t res; -__asm__ ("A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H) ;\n\t":"=&W" (res), - "=&d" - (b) -: "d" (a), "1" (b) -: "A1"); - return res; -} - -#undef MAC16_32_Q15 -static inline spx_word32_t -MAC16_32_Q15 (spx_word32_t c, spx_word16_t a, spx_word32_t b) -{ - spx_word32_t res; -__asm__ ("A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H);\n\t" "%0 = %0 + %4;\n\t":"=&W" (res), - "=&d" - (b) -: "d" (a), "1" (b), "d" (c) -: "A1"); - return res; -} - -#undef MULT16_32_Q14 -static inline spx_word32_t -MULT16_32_Q14 (spx_word16_t a, spx_word32_t b) -{ - spx_word32_t res; -__asm__ ("%2 <<= 1;\n\t" "A1 = %1.L*%2.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %1.L*%2.H);\n\t":"=W" (res), "=d" (a), - "=d" - (b) -: "1" (a), "2" (b) -: "A1"); - return res; -} - -#undef MAC16_32_Q14 -static inline spx_word32_t -MAC16_32_Q14 (spx_word32_t c, spx_word16_t a, spx_word32_t b) -{ - spx_word32_t res; -__asm__ ("%1 <<= 1;\n\t" "A1 = %2.L*%1.L (M);\n\t" "A1 = A1 >>> 15;\n\t" "%0 = (A1 += %2.L*%1.H);\n\t" "%0 = %0 + %4;\n\t":"=&W" (res), - "=&d" - (b) -: "d" (a), "1" (b), "d" (c) -: "A1"); - return res; -} - -#endif diff --git a/gst/speexresample/fixed_debug.h b/gst/speexresample/fixed_debug.h deleted file mode 100644 index 9ee8fa2a..00000000 --- a/gst/speexresample/fixed_debug.h +++ /dev/null @@ -1,525 +0,0 @@ -/* Copyright (C) 2003 Jean-Marc Valin */ -/** - @file fixed_debug.h - @brief Fixed-point operations with debugging -*/ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Neither the name of the Xiph.org Foundation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef FIXED_DEBUG_H -#define FIXED_DEBUG_H - -#include <stdio.h> - -extern long long spx_mips; -#define MIPS_INC spx_mips++, - -#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) -#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) - - -#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768) -#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL) - -static inline short -NEG16 (int x) -{ - int res; - if (!VERIFY_SHORT (x)) { - fprintf (stderr, "NEG16: input is not short: %d\n", (int) x); - } - res = -x; - if (!VERIFY_SHORT (res)) - fprintf (stderr, "NEG16: output is not short: %d\n", (int) res); - spx_mips++; - return res; -} - -static inline int -NEG32 (long long x) -{ - long long res; - if (!VERIFY_INT (x)) { - fprintf (stderr, "NEG16: input is not int: %d\n", (int) x); - } - res = -x; - if (!VERIFY_INT (res)) - fprintf (stderr, "NEG16: output is not int: %d\n", (int) res); - spx_mips++; - return res; -} - -#define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__) -static inline short -_EXTRACT16 (int x, char *file, int line) -{ - int res; - if (!VERIFY_SHORT (x)) { - fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, - file, line); - } - res = x; - spx_mips++; - return res; -} - -#define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__) -static inline int -_EXTEND32 (int x, char *file, int line) -{ - int res; - if (!VERIFY_SHORT (x)) { - fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, - file, line); - } - res = x; - spx_mips++; - return res; -} - -#define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__) -static inline short -_SHR16 (int a, int shift, char *file, int line) -{ - int res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (shift)) { - fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", - a, shift, file, line); - } - res = a >> shift; - if (!VERIFY_SHORT (res)) - fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, - file, line); - spx_mips++; - return res; -} - -#define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__) -static inline short -_SHL16 (int a, int shift, char *file, int line) -{ - int res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (shift)) { - fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, - shift, file, line); - } - res = a << shift; - if (!VERIFY_SHORT (res)) - fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, - file, line); - spx_mips++; - return res; -} - -static inline int -SHR32 (long long a, int shift) -{ - long long res; - if (!VERIFY_INT (a) || !VERIFY_SHORT (shift)) { - fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int) a, shift); - } - res = a >> shift; - if (!VERIFY_INT (res)) { - fprintf (stderr, "SHR32: output is not int: %d\n", (int) res); - } - spx_mips++; - return res; -} - -static inline int -SHL32 (long long a, int shift) -{ - long long res; - if (!VERIFY_INT (a) || !VERIFY_SHORT (shift)) { - fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int) a, shift); - } - res = a << shift; - if (!VERIFY_INT (res)) { - fprintf (stderr, "SHL32: output is not int: %d\n", (int) res); - } - spx_mips++; - return res; -} - -#define PSHR16(a,shift) (SHR16(ADD16((a),((1<<((shift))>>1))),shift)) -#define PSHR32(a,shift) (SHR32(ADD32((a),((EXTEND32(1)<<((shift))>>1))),shift)) -#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) - -#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) -#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) - -//#define SHR(a,shift) ((a) >> (shift)) -//#define SHL(a,shift) ((a) << (shift)) - -#define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__) -static inline short -_ADD16 (int a, int b, char *file, int line) -{ - int res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, - b, file, line); - } - res = a + b; - if (!VERIFY_SHORT (res)) { - fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a, - b, res, file, line); - } - spx_mips++; - return res; -} - -#define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__) -static inline short -_SUB16 (int a, int b, char *file, int line) -{ - int res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, - b, file, line); - } - res = a - b; - if (!VERIFY_SHORT (res)) - fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, - file, line); - spx_mips++; - return res; -} - -#define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__) -static inline int -_ADD32 (long long a, long long b, char *file, int line) -{ - long long res; - if (!VERIFY_INT (a) || !VERIFY_INT (b)) { - fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", - (int) a, (int) b, file, line); - } - res = a + b; - if (!VERIFY_INT (res)) { - fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int) res, - file, line); - } - spx_mips++; - return res; -} - -static inline int -SUB32 (long long a, long long b) -{ - long long res; - if (!VERIFY_INT (a) || !VERIFY_INT (b)) { - fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int) a, (int) b); - } - res = a - b; - if (!VERIFY_INT (res)) - fprintf (stderr, "SUB32: output is not int: %d\n", (int) res); - spx_mips++; - return res; -} - -#define ADD64(a,b) (MIPS_INC(a)+(b)) - -/* result fits in 16 bits */ -static inline short -MULT16_16_16 (int a, int b) -{ - int res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b); - } - res = a * b; - if (!VERIFY_SHORT (res)) - fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res); - spx_mips++; - return res; -} - -#define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__) -static inline int -_MULT16_16 (int a, int b, char *file, int line) -{ - long long res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", - a, b, file, line); - } - res = ((long long) a) * b; - if (!VERIFY_INT (res)) - fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", - (int) res, file, line); - spx_mips++; - return res; -} - -#define MAC16_16(c,a,b) (spx_mips--,ADD32((c),MULT16_16((a),(b)))) -#define MAC16_16_Q11(c,a,b) (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11))))) -#define MAC16_16_Q13(c,a,b) (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13))))) -#define MAC16_16_P13(c,a,b) (EXTRACT16(ADD32((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13)))) - - -#define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__) -static inline int -_MULT16_32_QX (int a, long long b, int Q, char *file, int line) -{ - long long res; - if (!VERIFY_SHORT (a) || !VERIFY_INT (b)) { - fprintf (stderr, - "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, - (int) a, (int) b, file, line); - } - if (ABS32 (b) >= (EXTEND32 (1) << (15 + Q))) - fprintf (stderr, - "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, - (int) a, (int) b, file, line); - res = (((long long) a) * (long long) b) >> Q; - if (!VERIFY_INT (res)) - fprintf (stderr, - "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, - (int) a, (int) b, (int) res, file, line); - spx_mips += 5; - return res; -} - -static inline int -MULT16_32_PX (int a, long long b, int Q) -{ - long long res; - if (!VERIFY_SHORT (a) || !VERIFY_INT (b)) { - fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, - (int) a, (int) b); - } - if (ABS32 (b) >= (EXTEND32 (1) << (15 + Q))) - fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, - (int) a, (int) b); - res = ((((long long) a) * (long long) b) + ((EXTEND32 (1) << Q) >> 1)) >> Q; - if (!VERIFY_INT (res)) - fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int) a, - (int) b, (int) res); - spx_mips += 5; - return res; -} - - -#define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11) -#define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b))) -#define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12) -#define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13) -#define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14) -#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15) -#define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15) -#define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b))) - -static inline int -SATURATE (int a, int b) -{ - if (a > b) - a = b; - if (a < -b) - a = -b; - return a; -} - -static inline int -MULT16_16_Q11_32 (int a, int b) -{ - long long res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b); - } - res = ((long long) a) * b; - res >>= 11; - if (!VERIFY_INT (res)) - fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int) a, - (int) b, (int) res); - spx_mips += 3; - return res; -} - -static inline short -MULT16_16_Q13 (int a, int b) -{ - long long res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b); - } - res = ((long long) a) * b; - res >>= 13; - if (!VERIFY_SHORT (res)) - fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, - (int) res); - spx_mips += 3; - return res; -} - -static inline short -MULT16_16_Q14 (int a, int b) -{ - long long res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b); - } - res = ((long long) a) * b; - res >>= 14; - if (!VERIFY_SHORT (res)) - fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int) res); - spx_mips += 3; - return res; -} - -static inline short -MULT16_16_Q15 (int a, int b) -{ - long long res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b); - } - res = ((long long) a) * b; - res >>= 15; - if (!VERIFY_SHORT (res)) { - fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int) res); - } - spx_mips += 3; - return res; -} - -static inline short -MULT16_16_P13 (int a, int b) -{ - long long res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b); - } - res = ((long long) a) * b; - res += 4096; - if (!VERIFY_INT (res)) - fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int) res); - res >>= 13; - if (!VERIFY_SHORT (res)) - fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, - (int) res); - spx_mips += 4; - return res; -} - -static inline short -MULT16_16_P14 (int a, int b) -{ - long long res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b); - } - res = ((long long) a) * b; - res += 8192; - if (!VERIFY_INT (res)) - fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int) res); - res >>= 14; - if (!VERIFY_SHORT (res)) - fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, - (int) res); - spx_mips += 4; - return res; -} - -static inline short -MULT16_16_P15 (int a, int b) -{ - long long res; - if (!VERIFY_SHORT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b); - } - res = ((long long) a) * b; - res += 16384; - if (!VERIFY_INT (res)) - fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int) res); - res >>= 15; - if (!VERIFY_SHORT (res)) - fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, - (int) res); - spx_mips += 4; - return res; -} - -#define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__) - -static inline int -_DIV32_16 (long long a, long long b, char *file, int line) -{ - long long res; - if (b == 0) { - fprintf (stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", - (int) a, (int) b, file, line); - return 0; - } - if (!VERIFY_INT (a) || !VERIFY_SHORT (b)) { - fprintf (stderr, - "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int) a, - (int) b, file, line); - } - res = a / b; - if (!VERIFY_SHORT (res)) { - fprintf (stderr, - "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int) a, - (int) b, (int) res, file, line); - if (res > 32767) - res = 32767; - if (res < -32768) - res = -32768; - } - spx_mips += 20; - return res; -} - -#define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__) -static inline int -_DIV32 (long long a, long long b, char *file, int line) -{ - long long res; - if (b == 0) { - fprintf (stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int) a, - (int) b, file, line); - return 0; - } - - if (!VERIFY_INT (a) || !VERIFY_INT (b)) { - fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", - (int) a, (int) b, file, line); - } - res = a / b; - if (!VERIFY_INT (res)) - fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int) res, - file, line); - spx_mips += 36; - return res; -} - -#define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b) -#define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b) - -#endif diff --git a/gst/speexresample/fixed_generic.h b/gst/speexresample/fixed_generic.h index 3fb096ed..2948177c 100644 --- a/gst/speexresample/fixed_generic.h +++ b/gst/speexresample/fixed_generic.h @@ -47,14 +47,14 @@ #define SHR32(a,shift) ((a) >> (shift)) #define SHL32(a,shift) ((a) << (shift)) #define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift)) -#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift)) +#define PSHR32(a,shift) (SHR32((a)+((1<<((shift))>>1)),shift)) #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) #define SHR(a,shift) ((a) >> (shift)) #define SHL(a,shift) ((spx_word32_t)(a) << (shift)) -#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift)) +#define PSHR(a,shift) (SHR((a)+((1<<((shift))>>1)),shift)) #define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) diff --git a/gst/speexresample/gstspeexresample.c b/gst/speexresample/gstspeexresample.c index 4c6dbffe..096c6b93 100644 --- a/gst/speexresample/gstspeexresample.c +++ b/gst/speexresample/gstspeexresample.c @@ -1,7 +1,7 @@ /* GStreamer * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu> * Copyright (C) 2003,2004 David A. Schleef <ds@schleef.org> - * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * 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 @@ -34,10 +34,6 @@ * </refsect2> */ -/* TODO: - * - Enable SSE/ARM optimizations and select at runtime - */ - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -49,18 +45,13 @@ #include <gst/audio/audio.h> #include <gst/base/gstbasetransform.h> -#define OIL_ENABLE_UNSTABLE_API -#include <liboil/liboilprofile.h> -#include <liboil/liboil.h> - GST_DEBUG_CATEGORY (speex_resample_debug); #define GST_CAT_DEFAULT speex_resample_debug enum { PROP_0, - PROP_QUALITY, - PROP_FILTER_LENGTH + PROP_QUALITY }; #define SUPPORTED_CAPS \ @@ -69,40 +60,16 @@ GST_STATIC_CAPS ( \ "rate = (int) [ 1, MAX ], " \ "channels = (int) [ 1, MAX ], " \ "endianness = (int) BYTE_ORDER, " \ - "width = (int) { 32, 64 }; " \ - "audio/x-raw-int, " \ - "rate = (int) [ 1, MAX ], " \ - "channels = (int) [ 1, MAX ], " \ - "endianness = (int) BYTE_ORDER, " \ - "width = (int) 32, " \ - "depth = (int) 32, " \ - "signed = (boolean) true; " \ - "audio/x-raw-int, " \ - "rate = (int) [ 1, MAX ], " \ - "channels = (int) [ 1, MAX ], " \ - "endianness = (int) BYTE_ORDER, " \ - "width = (int) 24, " \ - "depth = (int) 24, " \ - "signed = (boolean) true; " \ + "width = (int) 32; " \ "audio/x-raw-int, " \ "rate = (int) [ 1, MAX ], " \ "channels = (int) [ 1, MAX ], " \ "endianness = (int) BYTE_ORDER, " \ "width = (int) 16, " \ "depth = (int) 16, " \ - "signed = (boolean) true; " \ - "audio/x-raw-int, " \ - "rate = (int) [ 1, MAX ], " \ - "channels = (int) [ 1, MAX ], " \ - "endianness = (int) BYTE_ORDER, " \ - "width = (int) 8, " \ - "depth = (int) 8, " \ "signed = (boolean) true" \ ) -/* If TRUE integer arithmetic resampling is faster and will be used if appropiate */ -static gboolean gst_speex_resample_use_int = FALSE; - static GstStaticPadTemplate gst_speex_resample_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, SUPPORTED_CAPS); @@ -121,8 +88,6 @@ static gboolean gst_speex_resample_get_unit_size (GstBaseTransform * base, GstCaps * caps, guint * size); static GstCaps *gst_speex_resample_transform_caps (GstBaseTransform * base, GstPadDirection direction, GstCaps * caps); -static void gst_speex_resample_fixate_caps (GstBaseTransform * base, - GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); static gboolean gst_speex_resample_transform_size (GstBaseTransform * trans, GstPadDirection direction, GstCaps * incaps, guint insize, GstCaps * outcaps, guint * outsize); @@ -137,8 +102,11 @@ static gboolean gst_speex_resample_stop (GstBaseTransform * base); static gboolean gst_speex_resample_query (GstPad * pad, GstQuery * query); static const GstQueryType *gst_speex_resample_query_type (GstPad * pad); -GST_BOILERPLATE (GstSpeexResample, gst_speex_resample, GstBaseTransform, - GST_TYPE_BASE_TRANSFORM); +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (speex_resample_debug, "speex_resample", 0, "audio resampling element"); + +GST_BOILERPLATE_FULL (GstSpeexResample, gst_speex_resample, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); static void gst_speex_resample_base_init (gpointer g_class) @@ -152,7 +120,7 @@ gst_speex_resample_base_init (gpointer g_class) gst_element_class_set_details_simple (gstelement_class, "Audio resampler", "Filter/Converter/Audio", "Resamples audio", - "Sebastian Dröge <sebastian.droege@collabora.co.uk>"); + "Sebastian Dröge <slomo@circular-chaos.org>"); } static void @@ -170,14 +138,6 @@ gst_speex_resample_class_init (GstSpeexResampleClass * klass) SPEEX_RESAMPLER_QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - /* FIXME 0.11: Remove this property, it's just for compatibility - * with old audioresample - */ - g_object_class_install_property (gobject_class, PROP_FILTER_LENGTH, - g_param_spec_int ("filter-length", "Filter length", - "DEPRECATED, DON'T USE THIS! " "Length of the resample filter", 0, - G_MAXINT, 64, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - GST_BASE_TRANSFORM_CLASS (klass)->start = GST_DEBUG_FUNCPTR (gst_speex_resample_start); GST_BASE_TRANSFORM_CLASS (klass)->stop = @@ -188,8 +148,6 @@ gst_speex_resample_class_init (GstSpeexResampleClass * klass) GST_DEBUG_FUNCPTR (gst_speex_resample_get_unit_size); GST_BASE_TRANSFORM_CLASS (klass)->transform_caps = GST_DEBUG_FUNCPTR (gst_speex_resample_transform_caps); - GST_BASE_TRANSFORM_CLASS (klass)->fixate_caps = - GST_DEBUG_FUNCPTR (gst_speex_resample_fixate_caps); GST_BASE_TRANSFORM_CLASS (klass)->set_caps = GST_DEBUG_FUNCPTR (gst_speex_resample_set_caps); GST_BASE_TRANSFORM_CLASS (klass)->transform = @@ -221,9 +179,9 @@ gst_speex_resample_start (GstBaseTransform * base) { GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base); - resample->next_offset = -1; + resample->ts_offset = -1; + resample->offset = -1; resample->next_ts = -1; - resample->next_upstream_ts = -1; return TRUE; } @@ -234,20 +192,10 @@ gst_speex_resample_stop (GstBaseTransform * base) GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base); if (resample->state) { - resample->funcs->destroy (resample->state); + resample_resampler_destroy (resample->state); resample->state = NULL; } - resample->funcs = NULL; - - g_free (resample->tmp_in); - resample->tmp_in = NULL; - resample->tmp_in_size = 0; - - g_free (resample->tmp_out); - resample->tmp_out = NULL; - resample->tmp_out_size = 0; - gst_caps_replace (&resample->sinkcaps, NULL); gst_caps_replace (&resample->srccaps, NULL); @@ -268,11 +216,9 @@ gst_speex_resample_get_unit_size (GstBaseTransform * base, GstCaps * caps, structure = gst_caps_get_structure (caps, 0); ret = gst_structure_get_int (structure, "width", &width); ret &= gst_structure_get_int (structure, "channels", &channels); + g_return_val_if_fail (ret, FALSE); - if (G_UNLIKELY (!ret)) - return FALSE; - - *size = (width / 8) * channels; + *size = width * channels / 8; return TRUE; } @@ -293,64 +239,38 @@ gst_speex_resample_transform_caps (GstBaseTransform * base, return res; } -/* Fixate rate to the allowed rate that has the smallest difference */ -static void -gst_speex_resample_fixate_caps (GstBaseTransform * base, - GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) -{ - GstStructure *s; - gint rate; - - s = gst_caps_get_structure (caps, 0); - if (G_UNLIKELY (!gst_structure_get_int (s, "rate", &rate))) - return; - - s = gst_caps_get_structure (othercaps, 0); - 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 (gst_speex_resample_use_int && (width == 8 || width == 16) && !fp) - funcs = &int_funcs; - else if ((!gst_speex_resample_use_int && (width == 8 || width == 16) && !fp) - || (width == 32 && fp)) - funcs = &float_funcs; - else if ((width == 64 && fp) || ((width == 32 || width == 24) && !fp)) - funcs = &double_funcs; - else - g_assert_not_reached (); - - return funcs; -} - static SpeexResamplerState * -gst_speex_resample_init_state (GstSpeexResample * resample, gint width, - gint channels, gint inrate, gint outrate, gint quality, gboolean fp) +gst_speex_resample_init_state (guint channels, guint inrate, guint outrate, + guint quality, gboolean fp) { SpeexResamplerState *ret = NULL; gint err = RESAMPLER_ERR_SUCCESS; - const SpeexResampleFuncs *funcs = gst_speex_resample_get_funcs (width, fp); - ret = funcs->init (channels, inrate, outrate, quality, &err); + if (fp) + ret = + resample_float_resampler_init (channels, inrate, outrate, quality, + &err); + else + ret = + resample_int_resampler_init (channels, inrate, outrate, quality, &err); - if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) { - GST_ERROR_OBJECT (resample, "Failed to create resampler state: %s", - funcs->strerror (err)); + if (err != RESAMPLER_ERR_SUCCESS) { + GST_ERROR ("Failed to create resampler state: %s", + resample_resampler_strerror (err)); return NULL; } - funcs->skip_zeros (ret); + if (fp) + resample_float_resampler_skip_zeros (ret); + else + resample_int_resampler_skip_zeros (ret); return ret; } static gboolean -gst_speex_resample_update_state (GstSpeexResample * resample, gint width, - gint channels, gint inrate, gint outrate, gint quality, gboolean fp) +gst_speex_resample_update_state (GstSpeexResample * resample, gint channels, + gint inrate, gint outrate, gint quality, gboolean fp) { gboolean ret = TRUE; gboolean updated_latency = FALSE; @@ -360,38 +280,41 @@ gst_speex_resample_update_state (GstSpeexResample * resample, gint width, if (resample->state == NULL) { ret = TRUE; - } else if (resample->channels != channels || fp != resample->fp - || width != resample->width) { - resample->funcs->destroy (resample->state); + } else if (resample->channels != channels || fp != resample->fp) { + resample_resampler_destroy (resample->state); resample->state = - gst_speex_resample_init_state (resample, width, channels, inrate, - outrate, quality, fp); + gst_speex_resample_init_state (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; - err = resample->funcs->set_rate (resample->state, inrate, outrate); + if (fp) + err = + resample_float_resampler_set_rate (resample->state, inrate, outrate); + else + err = resample_int_resampler_set_rate (resample->state, inrate, outrate); - if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) - GST_ERROR_OBJECT (resample, "Failed to update rate: %s", - resample->funcs->strerror (err)); + if (err != RESAMPLER_ERR_SUCCESS) + GST_ERROR ("Failed to update rate: %s", + resample_resampler_strerror (err)); ret = (err == RESAMPLER_ERR_SUCCESS); } else if (quality != resample->quality) { gint err = RESAMPLER_ERR_SUCCESS; - err = resample->funcs->set_quality (resample->state, quality); + if (fp) + err = resample_float_resampler_set_quality (resample->state, quality); + else + err = resample_int_resampler_set_quality (resample->state, quality); - if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) - GST_ERROR_OBJECT (resample, "Failed to update quality: %s", - resample->funcs->strerror (err)); + if (err != RESAMPLER_ERR_SUCCESS) + GST_ERROR ("Failed to update quality: %s", + resample_resampler_strerror (err)); ret = (err == RESAMPLER_ERR_SUCCESS); } - resample->width = width; resample->channels = channels; resample->fp = fp; resample->quality = quality; @@ -408,18 +331,20 @@ gst_speex_resample_update_state (GstSpeexResample * resample, gint width, static void gst_speex_resample_reset_state (GstSpeexResample * resample) { - if (resample->state) - resample->funcs->reset_mem (resample->state); + 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); } static gboolean gst_speex_resample_parse_caps (GstCaps * incaps, - GstCaps * outcaps, gint * width, gint * channels, gint * inrate, - gint * outrate, gboolean * fp) + GstCaps * outcaps, gint * channels, gint * inrate, gint * outrate, + gboolean * fp) { GstStructure *structure; gboolean ret; - gint mywidth, myinrate, myoutrate, mychannels; + gint myinrate, myoutrate, mychannels; gboolean myfp; GST_DEBUG ("incaps %" GST_PTR_FORMAT ", outcaps %" @@ -434,13 +359,12 @@ 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)) + if (!ret) goto no_in_rate_channels; structure = gst_caps_get_structure (outcaps, 0); ret = gst_structure_get_int (structure, "rate", &myoutrate); - if (G_UNLIKELY (!ret)) + if (!ret) goto no_out_rate; if (channels) @@ -449,8 +373,7 @@ gst_speex_resample_parse_caps (GstCaps * incaps, *inrate = myinrate; if (outrate) *outrate = myoutrate; - if (width) - *width = mywidth; + if (fp) *fp = myfp; @@ -469,32 +392,20 @@ 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; - gint inrate, outrate, gcd; - gint width; + gboolean fp; - GST_LOG_OBJECT (resample, "asked to transform size %d in direction %s", + GST_LOG ("asked to transform size %d in direction %s", size, direction == GST_PAD_SINK ? "SINK" : "SRC"); if (direction == GST_PAD_SINK) { sinkcaps = caps; @@ -504,37 +415,59 @@ gst_speex_resample_transform_size (GstBaseTransform * base, srccaps = caps; } - 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 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 ("Can't use internal state, creating state"); + + ret = + gst_speex_resample_parse_caps (caps, othercaps, &channels, &inrate, + &outrate, &fp); + + if (!ret) { + GST_ERROR ("Wrong caps"); + return FALSE; + } + + state = gst_speex_resample_init_state (channels, inrate, outrate, 0, TRUE); + if (!state) + return FALSE; } - gcd = _gcd (inrate, outrate); - ratio_num = inrate / gcd; - ratio_den = outrate / gcd; + 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); if (direction == GST_PAD_SINK) { - gint fac = width / 8; + gint fac = (fp) ? 4 : 2; /* 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 *= fac; size *= fac; } else { - gint fac = width / 8; + gint fac = (fp) ? 4 : 2; /* 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 *= fac; size *= fac; } - GST_LOG_OBJECT (resample, "transformed size %d to %d", size, *othersize); + GST_LOG ("transformed size %d to %d", size, *othersize); + + if (!use_internal) + resample_resampler_destroy (state); return ret; } @@ -544,25 +477,23 @@ gst_speex_resample_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps) { gboolean ret; - gint width = 0, inrate = 0, outrate = 0, channels = 0; - gboolean fp; + gint inrate = 0, outrate = 0, channels = 0; + gboolean fp = FALSE; 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, - &width, &channels, &inrate, &outrate, &fp); + &channels, &inrate, &outrate, &fp); - if (G_UNLIKELY (!ret)) - return FALSE; + g_return_val_if_fail (ret, FALSE); ret = - gst_speex_resample_update_state (resample, width, channels, inrate, - outrate, resample->quality, fp); + gst_speex_resample_update_state (resample, channels, inrate, outrate, + resample->quality, fp); - if (G_UNLIKELY (!ret)) - return FALSE; + g_return_val_if_fail (ret, FALSE); /* save caps so we can short-circuit in the size_transform if the caps * are the same */ @@ -572,163 +503,6 @@ gst_speex_resample_set_caps (GstBaseTransform * base, GstCaps * incaps, return TRUE; } -#define GST_MAXINT24 (8388607) -#define GST_MININT24 (-8388608) - -#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) -#define GST_READ_UINT24 GST_READ_UINT24_LE -#define GST_WRITE_UINT24 GST_WRITE_UINT24_LE -#else -#define GST_READ_UINT24 GST_READ_UINT24_BE -#define GST_WRITE_UINT24 GST_WRITE_UINT24_BE -#endif - -static void -gst_speex_resample_convert_buffer (GstSpeexResample * resample, - const guint8 * in, guint8 * out, guint len, gboolean inverse) -{ - len *= resample->channels; - - if (inverse) { - if (gst_speex_resample_use_int && resample->width == 8 && !resample->fp) { - gint8 *o = (gint8 *) out; - gint16 *i = (gint16 *) in; - gint32 tmp; - - while (len) { - tmp = *i + (G_MAXINT8 >> 1); - *o = CLAMP (tmp >> 8, G_MININT8, G_MAXINT8); - o++; - i++; - len--; - } - } else if (!gst_speex_resample_use_int && resample->width == 8 - && !resample->fp) { - gint8 *o = (gint8 *) out; - gfloat *i = (gfloat *) in; - gfloat tmp; - - while (len) { - tmp = *i; - *o = (gint8) CLAMP (tmp * G_MAXINT8 + 0.5, G_MININT8, G_MAXINT8); - o++; - i++; - len--; - } - } else if (!gst_speex_resample_use_int && resample->width == 16 - && !resample->fp) { - gint16 *o = (gint16 *) out; - gfloat *i = (gfloat *) in; - gfloat tmp; - - while (len) { - tmp = *i; - *o = (gint16) CLAMP (tmp * G_MAXINT16 + 0.5, G_MININT16, G_MAXINT16); - o++; - i++; - len--; - } - } else if (resample->width == 24 && !resample->fp) { - guint8 *o = (guint8 *) out; - gdouble *i = (gdouble *) in; - gdouble tmp; - - while (len) { - tmp = *i; - GST_WRITE_UINT24 (o, (gint32) CLAMP (tmp * GST_MAXINT24 + 0.5, - GST_MININT24, GST_MAXINT24)); - o += 3; - i++; - len--; - } - } else if (resample->width == 32 && !resample->fp) { - gint32 *o = (gint32 *) out; - gdouble *i = (gdouble *) in; - gdouble tmp; - - while (len) { - tmp = *i; - *o = (gint32) CLAMP (tmp * G_MAXINT32 + 0.5, G_MININT32, G_MAXINT32); - o++; - i++; - len--; - } - } else { - g_assert_not_reached (); - } - } else { - if (gst_speex_resample_use_int && resample->width == 8 && !resample->fp) { - gint8 *i = (gint8 *) in; - gint16 *o = (gint16 *) out; - gint32 tmp; - - while (len) { - tmp = *i; - *o = tmp << 8; - o++; - i++; - len--; - } - } else if (!gst_speex_resample_use_int && resample->width == 8 - && !resample->fp) { - gint8 *i = (gint8 *) in; - gfloat *o = (gfloat *) out; - gfloat tmp; - - while (len) { - tmp = *i; - *o = tmp / G_MAXINT8; - o++; - i++; - len--; - } - } else if (!gst_speex_resample_use_int && resample->width == 16 - && !resample->fp) { - gint16 *i = (gint16 *) in; - gfloat *o = (gfloat *) out; - gfloat tmp; - - while (len) { - tmp = *i; - *o = tmp / G_MAXINT16; - o++; - i++; - len--; - } - } else if (resample->width == 24 && !resample->fp) { - guint8 *i = (guint8 *) in; - gdouble *o = (gdouble *) out; - gdouble tmp; - guint32 tmp2; - - while (len) { - tmp2 = GST_READ_UINT24 (i); - if (tmp2 & 0x00800000) - tmp2 |= 0xff000000; - tmp = (gint32) tmp2; - *o = tmp / GST_MAXINT24; - o++; - i += 3; - len--; - } - } else if (resample->width == 32 && !resample->fp) { - gint32 *i = (gint32 *) in; - gdouble *o = (gdouble *) out; - gdouble tmp; - - while (len) { - tmp = *i; - *o = tmp / G_MAXINT32; - o++; - i++; - len--; - } - } else { - g_assert_not_reached (); - } - } -} - static void gst_speex_resample_push_drain (GstSpeexResample * resample) { @@ -738,97 +512,97 @@ gst_speex_resample_push_drain (GstSpeexResample * resample) gint outsize; guint out_len, out_processed; gint err; - guint num, den, len; - guint8 *outtmp = NULL; - gboolean need_convert = FALSE; if (!resample->state) return; - need_convert = (resample->funcs->width != resample->width); + if (resample->fp) { + guint num, den; + + resample_float_resampler_get_ratio (resample->state, &num, &den); - resample->funcs->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; - 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; + resample_int_resampler_get_ratio (resample->state, &num, &den); - if (need_convert) { - guint outsize_tmp = - (resample->funcs->width / 8) * out_len * resample->channels; - if (outsize_tmp <= resample->tmp_out_size) { - outtmp = resample->tmp_out; - } else { - resample->tmp_out_size = outsize_tmp; - resample->tmp_out = outtmp = g_realloc (resample->tmp_out, outsize_tmp); - } + out_len = resample_int_resampler_get_input_latency (resample->state); + out_len = out_processed = (out_len * den + (num >> 1)) / num; + outsize = 2 * out_len * resample->channels; } - res = - gst_pad_alloc_buffer_and_set_caps (trans->srcpad, GST_BUFFER_OFFSET_NONE, - outsize, GST_PAD_CAPS (trans->srcpad), &buf); + res = gst_pad_alloc_buffer (trans->srcpad, GST_BUFFER_OFFSET_NONE, outsize, + GST_PAD_CAPS (trans->srcpad), &buf); if (G_UNLIKELY (res != GST_FLOW_OK)) { - GST_WARNING_OBJECT (resample, "failed allocating buffer of %d bytes", - outsize); + GST_WARNING ("failed allocating buffer of %d bytes", outsize); return; } - len = resample->funcs->get_input_latency (resample->state); + if (resample->fp) { + guint len = resample_float_resampler_get_input_latency (resample->state); - err = - resample->funcs->process (resample->state, - NULL, &len, (need_convert) ? outtmp : GST_BUFFER_DATA (buf), - &out_processed); + 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); + } - if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) { - GST_WARNING_OBJECT (resample, "Failed to process drain: %s", - resample->funcs->strerror (err)); + if (err != RESAMPLER_ERR_SUCCESS) { + GST_WARNING ("Failed to process drain: %s", + resample_resampler_strerror (err)); gst_buffer_unref (buf); return; } - if (G_UNLIKELY (out_processed == 0)) { - GST_WARNING_OBJECT (resample, "Failed to get drain, dropping buffer"); + if (out_processed == 0) { + GST_WARNING ("Failed to get drain, dropping buffer"); gst_buffer_unref (buf); return; } - /* If we wrote more than allocated something is really wrong now - * and we should better abort immediately */ - g_assert (out_len >= out_processed); - - if (need_convert) - gst_speex_resample_convert_buffer (resample, outtmp, GST_BUFFER_DATA (buf), - out_processed, TRUE); - - GST_BUFFER_DURATION (buf) = - GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate); + GST_BUFFER_OFFSET (buf) = resample->offset; + GST_BUFFER_TIMESTAMP (buf) = resample->next_ts; GST_BUFFER_SIZE (buf) = - out_processed * resample->channels * (resample->width / 8); - - if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) { - GST_BUFFER_OFFSET (buf) = resample->next_offset; - GST_BUFFER_OFFSET_END (buf) = resample->next_offset + out_processed; - GST_BUFFER_TIMESTAMP (buf) = resample->next_ts; - - resample->next_ts += GST_BUFFER_DURATION (buf); - resample->next_offset += out_processed; + out_processed * resample->channels * ((resample->fp) ? 4 : 2); + + if (resample->ts_offset != -1) { + resample->offset += out_processed; + resample->ts_offset += out_processed; + resample->next_ts = + GST_FRAMES_TO_CLOCK_TIME (resample->ts_offset, resample->outrate); + GST_BUFFER_OFFSET_END (buf) = resample->offset; + + /* we calculate DURATION as the difference between "next" timestamp + * and current timestamp so we ensure a contiguous stream, instead of + * having rounding errors. */ + GST_BUFFER_DURATION (buf) = resample->next_ts - GST_BUFFER_TIMESTAMP (buf); + } else { + /* no valid offset know, we can still sortof calculate the duration though */ + GST_BUFFER_DURATION (buf) = + GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate); } - GST_LOG_OBJECT (resample, - "Pushing drain buffer of %u bytes with timestamp %" GST_TIME_FORMAT - " duration %" GST_TIME_FORMAT " offset %" G_GUINT64_FORMAT " offset_end %" - G_GUINT64_FORMAT, GST_BUFFER_SIZE (buf), + GST_LOG ("Pushing drain buffer of %u bytes with timestamp %" GST_TIME_FORMAT + " duration %" GST_TIME_FORMAT " offset %" G_GUINT64_FORMAT + " offset_end %" G_GUINT64_FORMAT, + GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf), - GST_BUFFER_OFFSET_END (buf)); + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf)); res = gst_pad_push (trans->srcpad, buf); - if (G_UNLIKELY (res != GST_FLOW_OK)) - GST_WARNING_OBJECT (resample, "Failed to push drain: %s", - gst_flow_get_name (res)); + if (res != GST_FLOW_OK) + GST_WARNING ("Failed to push drain"); return; } @@ -843,15 +617,15 @@ gst_speex_resample_event (GstBaseTransform * base, GstEvent * event) break; case GST_EVENT_FLUSH_STOP: gst_speex_resample_reset_state (resample); - resample->next_offset = -1; + resample->ts_offset = -1; resample->next_ts = -1; - resample->next_upstream_ts = -1; + resample->offset = -1; case GST_EVENT_NEWSEGMENT: gst_speex_resample_push_drain (resample); gst_speex_resample_reset_state (resample); - resample->next_offset = -1; + resample->ts_offset = -1; resample->next_ts = -1; - resample->next_upstream_ts = -1; + resample->offset = -1; break; case GST_EVENT_EOS:{ gst_speex_resample_push_drain (resample); @@ -861,8 +635,9 @@ gst_speex_resample_event (GstBaseTransform * base, GstEvent * event) default: break; } + parent_class->event (base, event); - return parent_class->event (base, event); + return TRUE; } static gboolean @@ -870,18 +645,19 @@ gst_speex_resample_check_discont (GstSpeexResample * resample, GstClockTime timestamp) { if (timestamp != GST_CLOCK_TIME_NONE && - resample->next_upstream_ts != GST_CLOCK_TIME_NONE && - timestamp != resample->next_upstream_ts) { + resample->prev_ts != GST_CLOCK_TIME_NONE && + resample->prev_duration != GST_CLOCK_TIME_NONE && + timestamp != resample->prev_ts + resample->prev_duration) { /* Potentially a discontinuous buffer. However, it turns out that many * elements generate imperfect streams due to rounding errors, so we permit * a small error (up to one sample) without triggering a filter * flush/restart (if triggered incorrectly, this will be audible) */ - GstClockTimeDiff diff = timestamp - resample->next_upstream_ts; + GstClockTimeDiff diff = timestamp - + (resample->prev_ts + resample->prev_duration); - if (ABS (diff) > (GST_SECOND + resample->inrate - 1) / resample->inrate) { - GST_WARNING_OBJECT (resample, - "encountered timestamp discontinuity of %s%" GST_TIME_FORMAT, - (diff < 0) ? "-" : "", GST_TIME_ARGS ((GstClockTime) ABS (diff))); + if (ABS (diff) > GST_SECOND / resample->inrate) { + GST_WARNING ("encountered timestamp discontinuity of %" G_GINT64_FORMAT, + diff); return TRUE; } } @@ -889,6 +665,27 @@ gst_speex_resample_check_discont (GstSpeexResample * resample, return FALSE; } +static void +gst_speex_fix_output_buffer (GstSpeexResample * resample, GstBuffer * outbuf, + guint diff) +{ + GstClockTime timediff = GST_FRAMES_TO_CLOCK_TIME (diff, resample->outrate); + + GST_LOG ("Adjusting buffer by %d samples", diff); + + GST_BUFFER_DURATION (outbuf) -= timediff; + GST_BUFFER_SIZE (outbuf) -= + diff * ((resample->fp) ? 4 : 2) * resample->channels; + + if (resample->ts_offset != -1) { + GST_BUFFER_OFFSET_END (outbuf) -= diff; + resample->offset -= diff; + resample->ts_offset -= diff; + resample->next_ts = + GST_FRAMES_TO_CLOCK_TIME (resample->ts_offset, resample->outrate); + } +} + static GstFlowReturn gst_speex_resample_process (GstSpeexResample * resample, GstBuffer * inbuf, GstBuffer * outbuf) @@ -896,99 +693,70 @@ gst_speex_resample_process (GstSpeexResample * resample, GstBuffer * inbuf, guint32 in_len, in_processed; guint32 out_len, out_processed; gint err = RESAMPLER_ERR_SUCCESS; - guint8 *in_tmp = NULL, *out_tmp = NULL; - gboolean need_convert = (resample->funcs->width != resample->width); in_len = GST_BUFFER_SIZE (inbuf) / resample->channels; out_len = GST_BUFFER_SIZE (outbuf) / resample->channels; - in_len /= (resample->width / 8); - out_len /= (resample->width / 8); + if (resample->fp) { + in_len /= 4; + out_len /= 4; + } else { + in_len /= 2; + out_len /= 2; + } in_processed = in_len; out_processed = out_len; - if (need_convert) { - guint in_size_tmp = - in_len * resample->channels * (resample->funcs->width / 8); - guint out_size_tmp = - out_len * resample->channels * (resample->funcs->width / 8); - - if (in_size_tmp <= resample->tmp_in_size) { - in_tmp = resample->tmp_in; - } else { - resample->tmp_in = in_tmp = g_realloc (resample->tmp_in, in_size_tmp); - resample->tmp_in_size = in_size_tmp; - } - - gst_speex_resample_convert_buffer (resample, GST_BUFFER_DATA (inbuf), - in_tmp, in_len, FALSE); - - if (out_size_tmp <= resample->tmp_out_size) { - out_tmp = resample->tmp_out; - } else { - resample->tmp_out = out_tmp = g_realloc (resample->tmp_out, out_size_tmp); - resample->tmp_out_size = out_size_tmp; - } - } - - if (need_convert) { - err = resample->funcs->process (resample->state, - in_tmp, &in_processed, out_tmp, &out_processed); - } else { - err = resample->funcs->process (resample->state, - (const guint8 *) GST_BUFFER_DATA (inbuf), &in_processed, - (guint8 *) GST_BUFFER_DATA (outbuf), &out_processed); - } + 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); - if (G_UNLIKELY (in_len != in_processed)) - GST_WARNING_OBJECT (resample, "Converted %d of %d input samples", - in_processed, in_len); + if (in_len != in_processed) + GST_WARNING ("Converted %d of %d input samples", in_processed, in_len); if (out_len != out_processed) { + /* One sample difference is allowed as this will happen + * because of rounding errors */ if (out_processed == 0) { - GST_DEBUG_OBJECT (resample, "Converted to 0 samples, buffer dropped"); + GST_DEBUG ("Converted to 0 samples, buffer dropped"); + + if (resample->ts_offset != -1) { + GST_BUFFER_OFFSET_END (outbuf) -= out_len; + resample->offset -= out_len; + resample->ts_offset -= out_len; + resample->next_ts = + GST_FRAMES_TO_CLOCK_TIME (resample->ts_offset, resample->outrate); + } return GST_BASE_TRANSFORM_FLOW_DROPPED; + } else if (out_len - out_processed != 1) + GST_WARNING ("Converted to %d instead of %d output samples", + out_processed, out_len); + if (out_len > out_processed) { + gst_speex_fix_output_buffer (resample, outbuf, out_len - out_processed); + } else { + GST_ERROR ("Wrote more output than allocated!"); + return GST_FLOW_ERROR; } - - /* If we wrote more than allocated something is really wrong now - * and we should better abort immediately */ - g_assert (out_len >= out_processed); } - if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) { - GST_ERROR_OBJECT (resample, "Failed to convert data: %s", - resample->funcs->strerror (err)); + if (err != RESAMPLER_ERR_SUCCESS) { + GST_ERROR ("Failed to convert data: %s", resample_resampler_strerror (err)); return GST_FLOW_ERROR; } else { - - if (need_convert) - gst_speex_resample_convert_buffer (resample, out_tmp, - GST_BUFFER_DATA (outbuf), out_processed, TRUE); - - GST_BUFFER_DURATION (outbuf) = - GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate); - GST_BUFFER_SIZE (outbuf) = - out_processed * resample->channels * (resample->width / 8); - - if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) { - GST_BUFFER_TIMESTAMP (outbuf) = resample->next_ts; - GST_BUFFER_OFFSET (outbuf) = resample->next_offset; - GST_BUFFER_OFFSET_END (outbuf) = resample->next_offset + out_processed; - - resample->next_ts += GST_BUFFER_DURATION (outbuf); - resample->next_offset += out_processed; - } - - GST_LOG_OBJECT (resample, - "Converted to buffer of %u bytes with timestamp %" GST_TIME_FORMAT + GST_LOG ("Converted to buffer of %u bytes with timestamp %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT - ", offset_end %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (outbuf), + ", offset_end %" G_GUINT64_FORMAT, + GST_BUFFER_SIZE (outbuf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf), GST_BUFFER_OFFSET_END (outbuf)); - return GST_FLOW_OK; } } @@ -1001,25 +769,19 @@ gst_speex_resample_transform (GstBaseTransform * base, GstBuffer * inbuf, guint8 *data; gulong size; GstClockTime timestamp; - guint outsamples, insamples; - GstFlowReturn ret; + gint outsamples; - if (resample->state == NULL) { - if (G_UNLIKELY (!(resample->state = - gst_speex_resample_init_state (resample, resample->width, - resample->channels, resample->inrate, resample->outrate, - resample->quality, resample->fp)))) + if (resample->state == NULL) + if (!(resample->state = gst_speex_resample_init_state (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); - GST_LOG_OBJECT (resample, "transforming buffer of %ld bytes, ts %" + GST_LOG ("transforming buffer of %ld bytes, ts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT, size, GST_TIME_ARGS (timestamp), @@ -1033,44 +795,62 @@ gst_speex_resample_transform (GstBaseTransform * base, GstBuffer * inbuf, gst_speex_resample_reset_state (resample); /* Inform downstream element about discontinuity */ resample->need_discont = TRUE; - /* We want to recalculate the timestamps */ - resample->next_ts = -1; - resample->next_upstream_ts = -1; - resample->next_offset = -1; + /* We want to recalculate the offset */ + resample->ts_offset = -1; } - insamples = GST_BUFFER_SIZE (inbuf) / resample->channels; - insamples /= (resample->width / 8); - outsamples = GST_BUFFER_SIZE (outbuf) / resample->channels; - outsamples /= (resample->width / 8); + outsamples /= (resample->fp) ? 4 : 2; + + if (resample->ts_offset == -1) { + /* if we don't know the initial offset yet, calculate it based on the + * input timestamp. */ + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + GstClockTime stime; + + /* offset used to calculate the timestamps. We use the sample offset for + * this to make it more accurate. We want the first buffer to have the + * same timestamp as the incoming timestamp. */ + resample->next_ts = timestamp; + resample->ts_offset = + GST_CLOCK_TIME_TO_FRAMES (timestamp, resample->outrate); + /* offset used to set as the buffer offset, this offset is always + * relative to the stream time, note that timestamp is not... */ + stime = (timestamp - base->segment.start) + base->segment.time; + resample->offset = GST_CLOCK_TIME_TO_FRAMES (stime, resample->outrate); + } + } + resample->prev_ts = timestamp; + resample->prev_duration = GST_BUFFER_DURATION (inbuf); + + GST_BUFFER_OFFSET (outbuf) = resample->offset; + GST_BUFFER_TIMESTAMP (outbuf) = resample->next_ts; + + if (resample->ts_offset != -1) { + resample->offset += outsamples; + resample->ts_offset += outsamples; + resample->next_ts = + GST_FRAMES_TO_CLOCK_TIME (resample->ts_offset, resample->outrate); + GST_BUFFER_OFFSET_END (outbuf) = resample->offset; - if (GST_CLOCK_TIME_IS_VALID (timestamp) - && !GST_CLOCK_TIME_IS_VALID (resample->next_ts)) { - resample->next_ts = timestamp; - resample->next_offset = - GST_CLOCK_TIME_TO_FRAMES (timestamp, resample->outrate); + /* we calculate DURATION as the difference between "next" timestamp + * and current timestamp so we ensure a contiguous stream, instead of + * having rounding errors. */ + GST_BUFFER_DURATION (outbuf) = resample->next_ts - + GST_BUFFER_TIMESTAMP (outbuf); + } else { + /* no valid offset know, we can still sortof calculate the duration though */ + GST_BUFFER_DURATION (outbuf) = + GST_FRAMES_TO_CLOCK_TIME (outsamples, resample->outrate); } if (G_UNLIKELY (resample->need_discont)) { - GST_DEBUG_OBJECT (resample, "marking this buffer with the DISCONT flag"); + GST_DEBUG ("marking this buffer with the DISCONT flag"); GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); resample->need_discont = FALSE; } - ret = gst_speex_resample_process (resample, inbuf, outbuf); - if (G_UNLIKELY (ret != GST_FLOW_OK)) - return ret; - - if (GST_CLOCK_TIME_IS_VALID (timestamp) - && !GST_CLOCK_TIME_IS_VALID (resample->next_upstream_ts)) - resample->next_upstream_ts = timestamp; - - if (GST_CLOCK_TIME_IS_VALID (resample->next_upstream_ts)) - resample->next_upstream_ts += - GST_FRAMES_TO_CLOCK_TIME (insamples, resample->inrate); - - return GST_FLOW_OK; + return gst_speex_resample_process (resample, inbuf, outbuf); } static gboolean @@ -1090,9 +870,12 @@ gst_speex_resample_query (GstPad * pad, GstQuery * query) gint rate = resample->inrate; gint resampler_latency; - if (resample->state) + if (resample->state && resample->fp) + resampler_latency = + resample_float_resampler_get_input_latency (resample->state); + else if (resample->state && !resample->fp) resampler_latency = - resample->funcs->get_input_latency (resample->state); + resample_int_resampler_get_input_latency (resample->state); else resampler_latency = 0; @@ -1103,7 +886,7 @@ gst_speex_resample_query (GstPad * pad, GstQuery * query) if ((res = gst_pad_query (peer, query))) { gst_query_parse_latency (query, &live, &min, &max); - GST_DEBUG_OBJECT (resample, "Peer latency: min %" + GST_DEBUG ("Peer latency: min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT, GST_TIME_ARGS (min), GST_TIME_ARGS (max)); @@ -1114,14 +897,13 @@ gst_speex_resample_query (GstPad * pad, GstQuery * query) else latency = 0; - GST_DEBUG_OBJECT (resample, "Our latency: %" GST_TIME_FORMAT, - GST_TIME_ARGS (latency)); + GST_DEBUG ("Our latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (latency)); min += latency; if (max != GST_CLOCK_TIME_NONE) max += latency; - GST_DEBUG_OBJECT (resample, "Calculated total latency : min %" + GST_DEBUG ("Calculated total latency : min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT, GST_TIME_ARGS (min), GST_TIME_ARGS (max)); @@ -1161,45 +943,11 @@ gst_speex_resample_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_QUALITY: resample->quality = g_value_get_int (value); - GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality); + GST_DEBUG ("new quality %d", resample->quality); - gst_speex_resample_update_state (resample, resample->width, - resample->channels, resample->inrate, resample->outrate, - resample->quality, resample->fp); + gst_speex_resample_update_state (resample, resample->channels, + resample->inrate, resample->outrate, resample->quality, resample->fp); break; - case PROP_FILTER_LENGTH:{ - gint filter_length = g_value_get_int (value); - - if (filter_length <= 8) - resample->quality = 0; - else if (filter_length <= 16) - resample->quality = 1; - else if (filter_length <= 32) - resample->quality = 2; - else if (filter_length <= 48) - resample->quality = 3; - else if (filter_length <= 64) - resample->quality = 4; - else if (filter_length <= 80) - resample->quality = 5; - else if (filter_length <= 96) - resample->quality = 6; - else if (filter_length <= 128) - resample->quality = 7; - else if (filter_length <= 160) - resample->quality = 8; - else if (filter_length <= 192) - resample->quality = 9; - else - resample->quality = 10; - - GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality); - - 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); break; @@ -1218,177 +966,16 @@ gst_speex_resample_get_property (GObject * object, guint prop_id, case PROP_QUALITY: g_value_set_int (value, resample->quality); break; - case PROP_FILTER_LENGTH: - switch (resample->quality) { - case 0: - g_value_set_int (value, 8); - break; - case 1: - g_value_set_int (value, 16); - break; - case 2: - g_value_set_int (value, 32); - break; - case 3: - g_value_set_int (value, 48); - break; - case 4: - g_value_set_int (value, 64); - break; - case 5: - g_value_set_int (value, 80); - break; - case 6: - g_value_set_int (value, 96); - break; - case 7: - g_value_set_int (value, 128); - break; - case 8: - g_value_set_int (value, 160); - break; - case 9: - g_value_set_int (value, 192); - break; - case 10: - g_value_set_int (value, 256); - break; - } - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } -#define BENCHMARK_SIZE 512 - -static gboolean -_benchmark_int_float (SpeexResamplerState * st) -{ - gint16 in[BENCHMARK_SIZE] = { 0, }, out[BENCHMARK_SIZE / 2]; - gfloat in_tmp[BENCHMARK_SIZE], out_tmp[BENCHMARK_SIZE / 2]; - gint i; - guint32 inlen = BENCHMARK_SIZE, outlen = BENCHMARK_SIZE / 2; - - for (i = 0; i < BENCHMARK_SIZE; i++) { - gfloat tmp = in[i]; - in_tmp[i] = tmp / G_MAXINT16; - } - - resample_float_resampler_process_interleaved_float (st, - (const guint8 *) in_tmp, &inlen, (guint8 *) out_tmp, &outlen); - - if (outlen == 0) { - GST_ERROR ("Failed to use float resampler"); - return FALSE; - } - - for (i = 0; i < outlen; i++) { - gfloat tmp = out_tmp[i]; - out[i] = CLAMP (tmp * G_MAXINT16 + 0.5, G_MININT16, G_MAXINT16); - } - - return TRUE; -} - -static gboolean -_benchmark_int_int (SpeexResamplerState * st) -{ - gint16 in[BENCHMARK_SIZE] = { 0, }, out[BENCHMARK_SIZE / 2]; - guint32 inlen = BENCHMARK_SIZE, outlen = BENCHMARK_SIZE / 2; - - resample_int_resampler_process_interleaved_int (st, (const guint8 *) in, - &inlen, (guint8 *) out, &outlen); - - if (outlen == 0) { - GST_ERROR ("Failed to use int resampler"); - return FALSE; - } - - return TRUE; -} - -static gboolean -_benchmark_integer_resampling (void) -{ - OilProfile a, b; - gdouble av, bv; - SpeexResamplerState *sta, *stb; - - oil_profile_init (&a); - oil_profile_init (&b); - - sta = resample_float_resampler_init (1, 48000, 24000, 4, NULL); - if (sta == NULL) { - GST_ERROR ("Failed to create float resampler state"); - return FALSE; - } - - stb = resample_int_resampler_init (1, 48000, 24000, 4, NULL); - if (stb == NULL) { - resample_float_resampler_destroy (sta); - GST_ERROR ("Failed to create int resampler state"); - return FALSE; - } - - /* Warm up cache */ - if (!_benchmark_int_float (sta)) - goto error; - if (!_benchmark_int_float (sta)) - goto error; - - /* Benchmark */ - oil_profile_start (&a); - if (!_benchmark_int_float (sta)) - goto error; - oil_profile_stop (&a); - - /* Warm up cache */ - if (!_benchmark_int_int (stb)) - goto error; - if (!_benchmark_int_int (stb)) - goto error; - - /* Benchmark */ - oil_profile_start (&b); - if (!_benchmark_int_int (stb)) - goto error; - oil_profile_stop (&b); - - /* Handle results */ - oil_profile_get_ave_std (&a, &av, NULL); - oil_profile_get_ave_std (&b, &bv, NULL); - - gst_speex_resample_use_int = (av > bv); - resample_float_resampler_destroy (sta); - resample_float_resampler_destroy (stb); - - if (av > bv) - GST_DEBUG ("Using integer resampler if appropiate: %lf < %lf", bv, av); - else - GST_DEBUG ("Using float resampler for everything: %lf <= %lf", av, bv); - - return TRUE; - -error: - resample_float_resampler_destroy (sta); - resample_float_resampler_destroy (stb); - - return FALSE; -} static gboolean plugin_init (GstPlugin * plugin) { - GST_DEBUG_CATEGORY_INIT (speex_resample_debug, "speex_resample", 0, - "audio resampling element"); - - oil_init (); - - if (!_benchmark_integer_resampling ()) - return FALSE; - if (!gst_element_register (plugin, "speexresample", GST_RANK_NONE, GST_TYPE_SPEEX_RESAMPLE)) { return FALSE; diff --git a/gst/speexresample/gstspeexresample.h b/gst/speexresample/gstspeexresample.h index e39148a0..b5abf0e6 100644 --- a/gst/speexresample/gstspeexresample.h +++ b/gst/speexresample/gstspeexresample.h @@ -1,6 +1,6 @@ /* GStreamer * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * Copyright (C) <2007-2008> Sebastian Dröge <sebastian.droege@collabora.co.uk> + * 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 @@ -24,7 +24,6 @@ #include <gst/gst.h> #include <gst/base/gstbasetransform.h> -#include <gst/audio/audio.h> #include "speex_resampler_wrapper.h" @@ -58,25 +57,18 @@ struct _GstSpeexResample { gboolean need_discont; - guint64 next_offset; + guint64 offset; + guint64 ts_offset; GstClockTime next_ts; - GstClockTime next_upstream_ts; + GstClockTime prev_ts, prev_duration; - gint channels; - gint inrate; - gint outrate; - gint quality; - gint width; gboolean fp; - - guint8 *tmp_in; - guint tmp_in_size; - - guint8 *tmp_out; - guint tmp_out_size; + int channels; + int inrate; + int outrate; + int quality; SpeexResamplerState *state; - const SpeexResampleFuncs *funcs; }; struct _GstSpeexResampleClass { diff --git a/gst/speexresample/resample.c b/gst/speexresample/resample.c index f29e6144..29b95f23 100644 --- a/gst/speexresample/resample.c +++ b/gst/speexresample/resample.c @@ -1,5 +1,4 @@ -/* Copyright (C) 2007-2008 Jean-Marc Valin - Copyright (C) 2008 Thorvald Natvig +/* Copyright (C) 2007 Jean-Marc Valin File: resample.c Arbitrary resampling code @@ -63,17 +62,13 @@ #ifdef OUTSIDE_SPEEX #include <stdlib.h> - #include <glib.h> -#define EXPORT G_GNUC_INTERNAL - static inline void * speex_alloc (int size) { return g_malloc0 (size); } - static inline void * speex_realloc (void *ptr, int size) { @@ -90,7 +85,7 @@ speex_free (void *ptr) #include "arch.h" #else /* OUTSIDE_SPEEX */ -#include "../include/speex/speex_resampler.h" +#include "speex/speex_resampler.h" #include "arch.h" #include "os_support.h" #endif /* OUTSIDE_SPEEX */ @@ -107,6 +102,10 @@ speex_free (void *ptr) #define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) #endif +/*#define float double*/ +#define FILTER_SIZE 64 +#define OVERSAMPLE 8 + #define IMAX(a,b) ((a) > (b) ? (a) : (b)) #define IMIN(a,b) ((a) < (b) ? (a) : (b)) @@ -114,17 +113,6 @@ speex_free (void *ptr) #define NULL 0 #endif -#ifdef _USE_SSE -#include "resample_sse.h" -#endif - -/* Numer of elements to allocate on the stack */ -#ifdef VAR_ARRAYS -#define FIXED_STACK_ALLOC 8192 -#else -#define FIXED_STACK_ALLOC 1024 -#endif - typedef int (*resampler_basic_func) (SpeexResamplerState *, spx_uint32_t, const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); @@ -139,7 +127,6 @@ struct SpeexResamplerState_ spx_uint32_t nb_channels; spx_uint32_t filt_len; spx_uint32_t mem_alloc_size; - spx_uint32_t buffer_size; int int_advance; int frac_advance; float cutoff; @@ -267,19 +254,13 @@ 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; ind = (int) floor (y); frac = (y - ind); @@ -304,6 +285,7 @@ int main (int argc, char **argv) { int i; + for (i = 0; i < 256; i++) { printf ("%f\n", compute_func (i / 256., KAISER12)); } @@ -318,6 +300,7 @@ sinc (float cutoff, float x, int N, struct FuncDef *window_func) { /*fprintf (stderr, "%f ", x); */ float xx = x * cutoff; + if (fabs (x) < 1e-6f) return WORD2INT (32768. * cutoff); else if (fabs (x) > .5f * N) @@ -328,19 +311,12 @@ 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) @@ -358,6 +334,7 @@ cubic_coef (spx_word16_t x, spx_word16_t interp[4]) /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation but I know it's MMSE-optimal on a sinc */ spx_word16_t x2, x3; + x2 = MULT16_16_P15 (x, x); x3 = MULT16_16_P15 (x, x2); interp[0] = @@ -391,57 +368,57 @@ 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, spx_word16_t * out, spx_uint32_t * out_len) { - const int N = st->filt_len; + int N = st->filt_len; int out_sample = 0; + spx_word16_t *mem; int last_sample = st->last_sample[channel_index]; spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const spx_word16_t *sinc_table = st->sinc_table; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - spx_word32_t sum; - int j; + mem = st->mem + channel_index * st->mem_alloc_size; while (!(last_sample >= (spx_int32_t) * in_len || out_sample >= (spx_int32_t) * out_len)) { - const spx_word16_t *sinc = &sinc_table[samp_frac_num * N]; - const spx_word16_t *iptr = &in[last_sample]; + int j; + spx_word32_t sum = 0; -#ifndef OVERRIDE_INNER_PRODUCT_SINGLE - float accum[4] = { 0, 0, 0, 0 }; + /* We already have all the filter coefficients pre-computed in the table */ + const spx_word16_t *ptr; - for (j = 0; j < N; j += 4) { - accum[0] += sinc[j] * iptr[j]; - accum[1] += sinc[j + 1] * iptr[j + 1]; - accum[2] += sinc[j + 2] * iptr[j + 2]; - accum[3] += sinc[j + 3] * iptr[j + 3]; + /* Do the memory part */ + for (j = 0; last_sample - N + 1 + j < 0; j++) { + sum += + MULT16_16 (mem[last_sample + j], + st->sinc_table[samp_frac_num * st->filt_len + j]); } - sum = accum[0] + accum[1] + accum[2] + accum[3]; -#else - sum = inner_product_single (sinc, iptr, N); -#endif - out[out_stride * out_sample++] = PSHR32 (sum, 15); - last_sample += int_advance; - samp_frac_num += frac_advance; - if (samp_frac_num >= den_rate) { - samp_frac_num -= den_rate; + /* Do the new part */ + if (in != NULL) { + ptr = in + st->in_stride * (last_sample - N + 1 + j); + for (; j < N; j++) { + sum += + MULT16_16 (*ptr, st->sinc_table[samp_frac_num * st->filt_len + j]); + ptr += st->in_stride; + } + } + + *out = PSHR32 (sum, 15); + out += st->out_stride; + out_sample++; + last_sample += st->int_advance; + samp_frac_num += st->frac_advance; + if (samp_frac_num >= st->den_rate) { + samp_frac_num -= st->den_rate; last_sample++; } } - st->last_sample[channel_index] = last_sample; st->samp_frac_num[channel_index] = samp_frac_num; return out_sample; } -#endif #ifdef FIXED_POINT #else @@ -451,132 +428,150 @@ resampler_basic_direct_double (SpeexResamplerState * st, spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, spx_word16_t * out, spx_uint32_t * out_len) { - const int N = st->filt_len; + int N = st->filt_len; int out_sample = 0; + spx_word16_t *mem; int last_sample = st->last_sample[channel_index]; spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const spx_word16_t *sinc_table = st->sinc_table; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - double sum; - int j; + mem = st->mem + channel_index * st->mem_alloc_size; while (!(last_sample >= (spx_int32_t) * in_len || out_sample >= (spx_int32_t) * out_len)) { - const spx_word16_t *sinc = &sinc_table[samp_frac_num * N]; - const spx_word16_t *iptr = &in[last_sample]; + int j; + double sum = 0; -#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE - double accum[4] = { 0, 0, 0, 0 }; + /* We already have all the filter coefficients pre-computed in the table */ + const spx_word16_t *ptr; - for (j = 0; j < N; j += 4) { - accum[0] += sinc[j] * iptr[j]; - accum[1] += sinc[j + 1] * iptr[j + 1]; - accum[2] += sinc[j + 2] * iptr[j + 2]; - accum[3] += sinc[j + 3] * iptr[j + 3]; + /* Do the memory part */ + for (j = 0; last_sample - N + 1 + j < 0; j++) { + sum += + MULT16_16 (mem[last_sample + j], + (double) st->sinc_table[samp_frac_num * st->filt_len + j]); + } + + /* Do the new part */ + if (in != NULL) { + ptr = in + st->in_stride * (last_sample - N + 1 + j); + for (; j < N; j++) { + sum += + MULT16_16 (*ptr, + (double) st->sinc_table[samp_frac_num * st->filt_len + j]); + ptr += st->in_stride; + } } - sum = accum[0] + accum[1] + accum[2] + accum[3]; -#else - sum = inner_product_double (sinc, iptr, N); -#endif - out[out_stride * out_sample++] = PSHR32 (sum, 15); - last_sample += int_advance; - samp_frac_num += frac_advance; - if (samp_frac_num >= den_rate) { - samp_frac_num -= den_rate; + *out = sum; + out += st->out_stride; + out_sample++; + last_sample += st->int_advance; + samp_frac_num += st->frac_advance; + if (samp_frac_num >= st->den_rate) { + samp_frac_num -= st->den_rate; last_sample++; } } - st->last_sample[channel_index] = last_sample; st->samp_frac_num[channel_index] = samp_frac_num; return out_sample; } #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, spx_word16_t * out, spx_uint32_t * out_len) { - const int N = st->filt_len; + int N = st->filt_len; int out_sample = 0; + spx_word16_t *mem; int last_sample = st->last_sample[channel_index]; spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - int j; - spx_word32_t sum; + mem = st->mem + channel_index * st->mem_alloc_size; while (!(last_sample >= (spx_int32_t) * in_len || out_sample >= (spx_int32_t) * out_len)) { - const spx_word16_t *iptr = &in[last_sample]; + int j; + spx_word32_t sum = 0; + + /* We need to interpolate the sinc filter */ + spx_word32_t accum[4] = { 0.f, 0.f, 0.f, 0.f }; + spx_word16_t interp[4]; + const spx_word16_t *ptr; + int offset; + spx_word16_t frac; - const int offset = samp_frac_num * st->oversample / st->den_rate; + offset = samp_frac_num * st->oversample / st->den_rate; #ifdef FIXED_POINT - const spx_word16_t frac = + frac = PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15), st->den_rate); #else - const spx_word16_t frac = + frac = ((float) ((samp_frac_num * st->oversample) % st->den_rate)) / st->den_rate; #endif - spx_word16_t interp[4]; - - -#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE - spx_word32_t accum[4] = { 0, 0, 0, 0 }; + /* This code is written like this to make it easy to optimise with SIMD. + For most DSPs, it would be best to split the loops in two because most DSPs + have only two accumulators */ + for (j = 0; last_sample - N + 1 + j < 0; j++) { + spx_word16_t curr_mem = mem[last_sample + j]; - for (j = 0; j < N; j++) { - const spx_word16_t curr_in = iptr[j]; accum[0] += - MULT16_16 (curr_in, + MULT16_16 (curr_mem, st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]); accum[1] += - MULT16_16 (curr_in, + MULT16_16 (curr_mem, st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]); accum[2] += - MULT16_16 (curr_in, + MULT16_16 (curr_mem, st->sinc_table[4 + (j + 1) * st->oversample - offset]); accum[3] += - MULT16_16 (curr_in, + MULT16_16 (curr_mem, st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]); } + if (in != NULL) { + ptr = in + st->in_stride * (last_sample - N + 1 + j); + /* Do the new part */ + for (; j < N; j++) { + spx_word16_t curr_in = *ptr; + + ptr += st->in_stride; + accum[0] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]); + accum[1] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]); + accum[2] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset]); + accum[3] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]); + } + } cubic_coef (frac, interp); sum = MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1], accum[1]) + MULT16_32_Q15 (interp[2], accum[2]) + MULT16_32_Q15 (interp[3], accum[3]); -#else - cubic_coef (frac, interp); - sum = - interpolate_product_single (iptr, - st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, - interp); -#endif - out[out_stride * out_sample++] = PSHR32 (sum, 15); - last_sample += int_advance; - samp_frac_num += frac_advance; - if (samp_frac_num >= den_rate) { - samp_frac_num -= den_rate; + *out = PSHR32 (sum, 15); + out += st->out_stride; + out_sample++; + last_sample += st->int_advance; + samp_frac_num += st->frac_advance; + if (samp_frac_num >= st->den_rate) { + samp_frac_num -= st->den_rate; last_sample++; } } - st->last_sample[channel_index] = last_sample; st->samp_frac_num[channel_index] = samp_frac_num; return out_sample; } -#endif #ifdef FIXED_POINT #else @@ -586,81 +581,81 @@ resampler_basic_interpolate_double (SpeexResamplerState * st, spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, spx_word16_t * out, spx_uint32_t * out_len) { - const int N = st->filt_len; + int N = st->filt_len; int out_sample = 0; + spx_word16_t *mem; int last_sample = st->last_sample[channel_index]; spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; - const int out_stride = st->out_stride; - const int int_advance = st->int_advance; - const int frac_advance = st->frac_advance; - const spx_uint32_t den_rate = st->den_rate; - int j; - spx_word32_t sum; + mem = st->mem + channel_index * st->mem_alloc_size; while (!(last_sample >= (spx_int32_t) * in_len || out_sample >= (spx_int32_t) * out_len)) { - const spx_word16_t *iptr = &in[last_sample]; + int j; + spx_word32_t sum = 0; + + /* We need to interpolate the sinc filter */ + double accum[4] = { 0.f, 0.f, 0.f, 0.f }; + float interp[4]; + const spx_word16_t *ptr; + float alpha = ((float) samp_frac_num) / st->den_rate; + int offset = samp_frac_num * st->oversample / st->den_rate; + float frac = alpha * st->oversample - offset; + + /* This code is written like this to make it easy to optimise with SIMD. + For most DSPs, it would be best to split the loops in two because most DSPs + have only two accumulators */ + for (j = 0; last_sample - N + 1 + j < 0; j++) { + double curr_mem = mem[last_sample + j]; - const int offset = samp_frac_num * st->oversample / st->den_rate; -#ifdef FIXED_POINT - 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]; - - -#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE - double accum[4] = { 0, 0, 0, 0 }; - - for (j = 0; j < N; j++) { - const double curr_in = iptr[j]; accum[0] += - MULT16_16 (curr_in, + MULT16_16 (curr_mem, st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]); accum[1] += - MULT16_16 (curr_in, + MULT16_16 (curr_mem, st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]); accum[2] += - MULT16_16 (curr_in, + MULT16_16 (curr_mem, st->sinc_table[4 + (j + 1) * st->oversample - offset]); accum[3] += - MULT16_16 (curr_in, + MULT16_16 (curr_mem, st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]); } - - cubic_coef (frac, interp); - sum = - MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1], - accum[1]) + MULT16_32_Q15 (interp[2], - accum[2]) + MULT16_32_Q15 (interp[3], accum[3]); -#else + if (in != NULL) { + ptr = in + st->in_stride * (last_sample - N + 1 + j); + /* Do the new part */ + for (; j < N; j++) { + double curr_in = *ptr; + + ptr += st->in_stride; + accum[0] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]); + accum[1] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]); + accum[2] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset]); + accum[3] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]); + } + } cubic_coef (frac, interp); sum = - interpolate_product_double (iptr, - st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, - interp); -#endif - - out[out_stride * out_sample++] = PSHR32 (sum, 15); - last_sample += int_advance; - samp_frac_num += frac_advance; - if (samp_frac_num >= den_rate) { - samp_frac_num -= den_rate; + interp[0] * accum[0] + interp[1] * accum[1] + interp[2] * accum[2] + + interp[3] * accum[3]; + + *out = PSHR32 (sum, 15); + out += st->out_stride; + out_sample++; + last_sample += st->int_advance; + samp_frac_num += st->frac_advance; + if (samp_frac_num >= st->den_rate) { + samp_frac_num -= st->den_rate; last_sample++; } } - st->last_sample[channel_index] = last_sample; st->samp_frac_num[channel_index] = samp_frac_num; return out_sample; @@ -703,6 +698,7 @@ update_filter (SpeexResamplerState * st) /* Choose the resampling type that requires the least amount of memory */ if (st->den_rate <= st->oversample) { spx_uint32_t i; + if (!st->sinc_table) st->sinc_table = (spx_word16_t *) speex_alloc (st->filt_len * st->den_rate * @@ -715,32 +711,27 @@ update_filter (SpeexResamplerState * st) } for (i = 0; i < st->den_rate; i++) { 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) - -#ifdef DOUBLE_PRECISION - ((double) i) / st->den_rate), st->filt_len, -#else + sinc (st->cutoff, + ((j - (spx_int32_t) st->filt_len / 2 + 1) - ((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; + if (!st->sinc_table) st->sinc_table = (spx_word16_t *) speex_alloc ((st->filt_len * st->oversample + @@ -753,24 +744,16 @@ 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; @@ -782,36 +765,41 @@ update_filter (SpeexResamplerState * st) due to handling of lots of corner cases. */ if (!st->mem) { spx_uint32_t i; - st->mem_alloc_size = st->filt_len - 1 + st->buffer_size; + st->mem = - (spx_word16_t *) speex_alloc (st->nb_channels * st->mem_alloc_size * - sizeof (spx_word16_t)); - for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++) + (spx_word16_t *) speex_alloc (st->nb_channels * (st->filt_len - + 1) * sizeof (spx_word16_t)); + for (i = 0; i < st->nb_channels * (st->filt_len - 1); i++) st->mem[i] = 0; + st->mem_alloc_size = st->filt_len - 1; /*speex_warning("init filter"); */ } else if (!st->started) { spx_uint32_t i; - st->mem_alloc_size = st->filt_len - 1 + st->buffer_size; + st->mem = (spx_word16_t *) speex_realloc (st->mem, - st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t)); - for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++) + st->nb_channels * (st->filt_len - 1) * sizeof (spx_word16_t)); + for (i = 0; i < st->nb_channels * (st->filt_len - 1); i++) st->mem[i] = 0; + st->mem_alloc_size = st->filt_len - 1; /*speex_warning("reinit filter"); */ } else if (st->filt_len > old_length) { spx_int32_t i; + /* Increase the filter length */ /*speex_warning("increase filter size"); */ int old_alloc_size = st->mem_alloc_size; - if ((st->filt_len - 1 + st->buffer_size) > st->mem_alloc_size) { - st->mem_alloc_size = st->filt_len - 1 + st->buffer_size; + + if (st->filt_len - 1 > st->mem_alloc_size) { st->mem = (spx_word16_t *) speex_realloc (st->mem, - st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t)); + st->nb_channels * (st->filt_len - 1) * sizeof (spx_word16_t)); + st->mem_alloc_size = st->filt_len - 1; } for (i = st->nb_channels - 1; i >= 0; i--) { spx_int32_t j; spx_uint32_t olen = old_length; + /*if (st->magic_samples[i]) */ { /* Try and remove the magic samples as if nothing had happened */ @@ -846,11 +834,13 @@ update_filter (SpeexResamplerState * st) } } else if (st->filt_len < old_length) { spx_uint32_t i; + /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic" samples so they can be used directly as input the next time(s) */ for (i = 0; i < st->nb_channels; i++) { spx_uint32_t j; spx_uint32_t old_magic = st->magic_samples[i]; + st->magic_samples[i] = (old_length - st->filt_len) / 2; /* We must copy some of the memory that's no longer used */ /* Copy data going backward */ @@ -863,7 +853,7 @@ update_filter (SpeexResamplerState * st) } -EXPORT SpeexResamplerState * +SpeexResamplerState * speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) { @@ -871,13 +861,14 @@ speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate, out_rate, quality, err); } -EXPORT SpeexResamplerState * +SpeexResamplerState * speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err) { spx_uint32_t i; SpeexResamplerState *st; + if (quality > 10 || quality < 0) { if (err) *err = RESAMPLER_ERR_INVALID_ARG; @@ -902,12 +893,6 @@ speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num, st->in_stride = 1; st->out_stride = 1; -#ifdef FIXED_POINT - st->buffer_size = 160; -#else - st->buffer_size = 160; -#endif - /* Per channel data */ st->last_sample = (spx_int32_t *) speex_alloc (nb_channels * sizeof (int)); st->magic_samples = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int)); @@ -931,7 +916,7 @@ speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num, return st; } -EXPORT void +void speex_resampler_destroy (SpeexResamplerState * st) { speex_free (st->mem); @@ -942,207 +927,249 @@ speex_resampler_destroy (SpeexResamplerState * st) speex_free (st); } + + static int speex_resampler_process_native (SpeexResamplerState * st, - spx_uint32_t channel_index, spx_uint32_t * in_len, spx_word16_t * out, - spx_uint32_t * out_len) + spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, + spx_word16_t * out, spx_uint32_t * out_len) { int j = 0; - const int N = st->filt_len; + int N = st->filt_len; int out_sample = 0; - spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; - spx_uint32_t ilen; + spx_word16_t *mem; + spx_uint32_t tmp_out_len = 0; + mem = st->mem + channel_index * st->mem_alloc_size; st->started = 1; + /* Handle the case where we have samples left from a reduction in filter length */ + if (st->magic_samples[channel_index]) { + int istride_save; + spx_uint32_t tmp_in_len; + spx_uint32_t tmp_magic; + + istride_save = st->in_stride; + tmp_in_len = st->magic_samples[channel_index]; + tmp_out_len = *out_len; + /* magic_samples needs to be set to zero to avoid infinite recursion */ + tmp_magic = st->magic_samples[channel_index]; + st->magic_samples[channel_index] = 0; + st->in_stride = 1; + speex_resampler_process_native (st, channel_index, mem + N - 1, &tmp_in_len, + out, &tmp_out_len); + st->in_stride = istride_save; + /*speex_warning_int("extra samples:", tmp_out_len); */ + /* If we couldn't process all "magic" input samples, save the rest for next time */ + if (tmp_in_len < tmp_magic) { + spx_uint32_t i; + + st->magic_samples[channel_index] = tmp_magic - tmp_in_len; + for (i = 0; i < st->magic_samples[channel_index]; i++) + mem[N - 1 + i] = mem[N - 1 + i + tmp_in_len]; + } + out += tmp_out_len * st->out_stride; + *out_len -= tmp_out_len; + } + /* Call the right resampler through the function ptr */ - out_sample = st->resampler_ptr (st, channel_index, mem, in_len, out, out_len); + out_sample = st->resampler_ptr (st, channel_index, in, in_len, out, out_len); if (st->last_sample[channel_index] < (spx_int32_t) * in_len) *in_len = st->last_sample[channel_index]; - *out_len = out_sample; + *out_len = out_sample + tmp_out_len; st->last_sample[channel_index] -= *in_len; - ilen = *in_len; - - for (j = 0; j < N - 1; ++j) - mem[j] = mem[j + ilen]; - + for (j = 0; j < N - 1 - (spx_int32_t) * in_len; j++) + mem[j] = mem[j + *in_len]; + if (in != NULL) { + for (; j < N - 1; j++) + mem[j] = in[st->in_stride * (j + *in_len - N + 1)]; + } else { + for (; j < N - 1; j++) + mem[j] = 0; + } return RESAMPLER_ERR_SUCCESS; } -static int -speex_resampler_magic (SpeexResamplerState * st, spx_uint32_t channel_index, - spx_word16_t ** out, spx_uint32_t out_len) +#define FIXED_STACK_ALLOC 1024 + +#ifdef FIXED_POINT +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) { - spx_uint32_t tmp_in_len = st->magic_samples[channel_index]; - spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; - const int N = st->filt_len; + spx_uint32_t i; + int istride_save, ostride_save; - speex_resampler_process_native (st, channel_index, &tmp_in_len, *out, - &out_len); +#ifdef VAR_ARRAYS + spx_word16_t x[*in_len]; + spx_word16_t y[*out_len]; - st->magic_samples[channel_index] -= tmp_in_len; + /*VARDECL(spx_word16_t *x); + VARDECL(spx_word16_t *y); + ALLOC(x, *in_len, spx_word16_t); + ALLOC(y, *out_len, spx_word16_t); */ + istride_save = st->in_stride; + ostride_save = st->out_stride; + if (in != NULL) { + for (i = 0; i < *in_len; i++) + x[i] = WORD2INT (in[i * st->in_stride]); + st->in_stride = st->out_stride = 1; + speex_resampler_process_native (st, channel_index, x, in_len, y, out_len); + } else { + st->in_stride = st->out_stride = 1; + speex_resampler_process_native (st, channel_index, NULL, in_len, y, + out_len); + } + st->in_stride = istride_save; + st->out_stride = ostride_save; + for (i = 0; i < *out_len; i++) + out[i * st->out_stride] = y[i]; +#else + spx_word16_t x[FIXED_STACK_ALLOC]; + spx_word16_t y[FIXED_STACK_ALLOC]; + spx_uint32_t ilen = *in_len, olen = *out_len; - /* If we couldn't process all "magic" input samples, save the rest for next time */ - if (st->magic_samples[channel_index]) { - spx_uint32_t i; - for (i = 0; i < st->magic_samples[channel_index]; i++) - mem[N - 1 + i] = mem[N - 1 + i + tmp_in_len]; + istride_save = st->in_stride; + ostride_save = st->out_stride; + while (ilen && olen) { + spx_uint32_t ichunk, ochunk; + + ichunk = ilen; + ochunk = olen; + if (ichunk > FIXED_STACK_ALLOC) + ichunk = FIXED_STACK_ALLOC; + if (ochunk > FIXED_STACK_ALLOC) + ochunk = FIXED_STACK_ALLOC; + if (in != NULL) { + for (i = 0; i < ichunk; i++) + x[i] = WORD2INT (in[i * st->in_stride]); + st->in_stride = st->out_stride = 1; + speex_resampler_process_native (st, channel_index, x, &ichunk, y, + &ochunk); + } else { + st->in_stride = st->out_stride = 1; + speex_resampler_process_native (st, channel_index, NULL, &ichunk, y, + &ochunk); + } + st->in_stride = istride_save; + st->out_stride = ostride_save; + for (i = 0; i < ochunk; i++) + out[i * st->out_stride] = y[i]; + out += ochunk; + in += ichunk; + ilen -= ichunk; + olen -= ochunk; } - *out += out_len * st->out_stride; - return out_len; + *in_len -= ilen; + *out_len -= olen; +#endif + return RESAMPLER_ERR_SUCCESS; } -#ifdef FIXED_POINT -EXPORT int +int 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) +{ + return speex_resampler_process_native (st, channel_index, in, in_len, out, + 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 +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; - spx_uint32_t olen = *out_len; - spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; - const int filt_offs = st->filt_len - 1; - const spx_uint32_t xlen = st->mem_alloc_size - filt_offs; - const int istride = st->in_stride; - - if (st->magic_samples[channel_index]) - olen -= speex_resampler_magic (st, channel_index, &out, olen); - if (!st->magic_samples[channel_index]) { - while (ilen && olen) { - spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; - spx_uint32_t ochunk = olen; - - if (in) { - for (j = 0; j < ichunk; ++j) - x[j + filt_offs] = in[j * istride]; - } else { - for (j = 0; j < ichunk; ++j) - x[j + filt_offs] = 0; - } - speex_resampler_process_native (st, channel_index, &ichunk, out, &ochunk); - ilen -= ichunk; - olen -= ochunk; - out += ochunk * st->out_stride; - if (in) - in += ichunk * istride; - } - } - *in_len -= ilen; - *out_len -= olen; - return RESAMPLER_ERR_SUCCESS; + return speex_resampler_process_native (st, channel_index, in, in_len, out, + out_len); } -#ifdef FIXED_POINT -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) -#else -EXPORT int +int 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) -#endif { - int j; - const int istride_save = st->in_stride; - const int ostride_save = st->out_stride; - spx_uint32_t ilen = *in_len; - spx_uint32_t olen = *out_len; - spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; - const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1); -#ifdef VAR_ARRAYS - const unsigned int ylen = - (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC; - VARDECL (spx_word16_t * ystack); - ALLOC (ystack, ylen, spx_word16_t); -#else - const unsigned int ylen = FIXED_STACK_ALLOC; - spx_word16_t ystack[FIXED_STACK_ALLOC]; -#endif + spx_uint32_t i; + int istride_save, ostride_save; - st->out_stride = 1; +#ifdef VAR_ARRAYS + spx_word16_t x[*in_len]; + spx_word16_t y[*out_len]; - while (ilen && olen) { - spx_word16_t *y = ystack; - spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; - spx_uint32_t ochunk = (olen > ylen) ? ylen : olen; - spx_uint32_t omagic = 0; - - if (st->magic_samples[channel_index]) { - omagic = speex_resampler_magic (st, channel_index, &y, ochunk); - ochunk -= omagic; - olen -= omagic; - } - if (!st->magic_samples[channel_index]) { - if (in) { - for (j = 0; j < ichunk; ++j) -#ifdef FIXED_POINT - x[j + st->filt_len - 1] = WORD2INT (in[j * istride_save]); + /*VARDECL(spx_word16_t *x); + VARDECL(spx_word16_t *y); + ALLOC(x, *in_len, spx_word16_t); + ALLOC(y, *out_len, spx_word16_t); */ + istride_save = st->in_stride; + ostride_save = st->out_stride; + if (in != NULL) { + for (i = 0; i < *in_len; i++) + x[i] = in[i * st->in_stride]; + st->in_stride = st->out_stride = 1; + speex_resampler_process_native (st, channel_index, x, in_len, y, out_len); + } else { + st->in_stride = st->out_stride = 1; + speex_resampler_process_native (st, channel_index, NULL, in_len, y, + out_len); + } + st->in_stride = istride_save; + st->out_stride = ostride_save; + for (i = 0; i < *out_len; i++) + out[i * st->out_stride] = WORD2INT (y[i]); #else - x[j + st->filt_len - 1] = in[j * istride_save]; -#endif - } else { - for (j = 0; j < ichunk; ++j) - x[j + st->filt_len - 1] = 0; - } + spx_word16_t x[FIXED_STACK_ALLOC]; + spx_word16_t y[FIXED_STACK_ALLOC]; + spx_uint32_t ilen = *in_len, olen = *out_len; - speex_resampler_process_native (st, channel_index, &ichunk, y, &ochunk); + istride_save = st->in_stride; + ostride_save = st->out_stride; + while (ilen && olen) { + spx_uint32_t ichunk, ochunk; + + ichunk = ilen; + ochunk = olen; + if (ichunk > FIXED_STACK_ALLOC) + ichunk = FIXED_STACK_ALLOC; + if (ochunk > FIXED_STACK_ALLOC) + ochunk = FIXED_STACK_ALLOC; + if (in != NULL) { + for (i = 0; i < ichunk; i++) + x[i] = in[i * st->in_stride]; + st->in_stride = st->out_stride = 1; + speex_resampler_process_native (st, channel_index, x, &ichunk, y, + &ochunk); } else { - ichunk = 0; - ochunk = 0; + st->in_stride = st->out_stride = 1; + speex_resampler_process_native (st, channel_index, NULL, &ichunk, y, + &ochunk); } - - for (j = 0; j < ochunk + omagic; ++j) -#ifdef FIXED_POINT - out[j * ostride_save] = ystack[j]; -#else - out[j * ostride_save] = WORD2INT (ystack[j]); -#endif - + st->in_stride = istride_save; + st->out_stride = ostride_save; + for (i = 0; i < ochunk; i++) + out[i * st->out_stride] = WORD2INT (y[i]); + out += ochunk; + in += ichunk; ilen -= ichunk; olen -= ochunk; - out += (ochunk + omagic) * ostride_save; - if (in) - in += ichunk * istride_save; } - st->out_stride = ostride_save; *in_len -= ilen; *out_len -= olen; - +#endif return RESAMPLER_ERR_SUCCESS; } +#endif -#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 +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; spx_uint32_t bak_len = *out_len; + istride_save = st->in_stride; ostride_save = st->out_stride; st->in_stride = st->out_stride = st->nb_channels; @@ -1158,7 +1185,8 @@ speex_resampler_process_interleaved_float (SpeexResamplerState * st, return RESAMPLER_ERR_SUCCESS; } -EXPORT int + +int speex_resampler_process_interleaved_int (SpeexResamplerState * st, const spx_int16_t * in, spx_uint32_t * in_len, spx_int16_t * out, spx_uint32_t * out_len) @@ -1166,6 +1194,7 @@ speex_resampler_process_interleaved_int (SpeexResamplerState * st, spx_uint32_t i; int istride_save, ostride_save; spx_uint32_t bak_len = *out_len; + istride_save = st->in_stride; ostride_save = st->out_stride; st->in_stride = st->out_stride = st->nb_channels; @@ -1181,7 +1210,7 @@ speex_resampler_process_interleaved_int (SpeexResamplerState * st, return RESAMPLER_ERR_SUCCESS; } -EXPORT int +int speex_resampler_set_rate (SpeexResamplerState * st, spx_uint32_t in_rate, spx_uint32_t out_rate) { @@ -1189,7 +1218,7 @@ speex_resampler_set_rate (SpeexResamplerState * st, spx_uint32_t in_rate, out_rate); } -EXPORT void +void speex_resampler_get_rate (SpeexResamplerState * st, spx_uint32_t * in_rate, spx_uint32_t * out_rate) { @@ -1197,13 +1226,14 @@ speex_resampler_get_rate (SpeexResamplerState * st, spx_uint32_t * in_rate, *out_rate = st->out_rate; } -EXPORT int +int speex_resampler_set_rate_frac (SpeexResamplerState * st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate) { spx_uint32_t fact; spx_uint32_t old_den; spx_uint32_t i; + if (st->in_rate == in_rate && st->out_rate == out_rate && st->num_rate == ratio_num && st->den_rate == ratio_den) return RESAMPLER_ERR_SUCCESS; @@ -1235,7 +1265,7 @@ speex_resampler_set_rate_frac (SpeexResamplerState * st, spx_uint32_t ratio_num, return RESAMPLER_ERR_SUCCESS; } -EXPORT void +void speex_resampler_get_ratio (SpeexResamplerState * st, spx_uint32_t * ratio_num, spx_uint32_t * ratio_den) { @@ -1243,7 +1273,7 @@ speex_resampler_get_ratio (SpeexResamplerState * st, spx_uint32_t * ratio_num, *ratio_den = st->den_rate; } -EXPORT int +int speex_resampler_set_quality (SpeexResamplerState * st, int quality) { if (quality > 10 || quality < 0) @@ -1256,71 +1286,73 @@ speex_resampler_set_quality (SpeexResamplerState * st, int quality) return RESAMPLER_ERR_SUCCESS; } -EXPORT void +void speex_resampler_get_quality (SpeexResamplerState * st, int *quality) { *quality = st->quality; } -EXPORT void +void speex_resampler_set_input_stride (SpeexResamplerState * st, spx_uint32_t stride) { st->in_stride = stride; } -EXPORT void +void speex_resampler_get_input_stride (SpeexResamplerState * st, spx_uint32_t * stride) { *stride = st->in_stride; } -EXPORT void +void speex_resampler_set_output_stride (SpeexResamplerState * st, spx_uint32_t stride) { st->out_stride = stride; } -EXPORT void +void speex_resampler_get_output_stride (SpeexResamplerState * st, spx_uint32_t * stride) { *stride = st->out_stride; } -EXPORT int +int speex_resampler_get_input_latency (SpeexResamplerState * st) { return st->filt_len / 2; } -EXPORT int +int speex_resampler_get_output_latency (SpeexResamplerState * st) { return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate; } -EXPORT int +int speex_resampler_skip_zeros (SpeexResamplerState * st) { spx_uint32_t i; + for (i = 0; i < st->nb_channels; i++) st->last_sample[i] = st->filt_len / 2; return RESAMPLER_ERR_SUCCESS; } -EXPORT int +int speex_resampler_reset_mem (SpeexResamplerState * st) { spx_uint32_t i; + for (i = 0; i < st->nb_channels * (st->filt_len - 1); i++) st->mem[i] = 0; return RESAMPLER_ERR_SUCCESS; } -EXPORT const char * +const char * speex_resampler_strerror (int err) { switch (err) { diff --git a/gst/speexresample/resample_sse.h b/gst/speexresample/resample_sse.h deleted file mode 100644 index 4bd35a2d..00000000 --- a/gst/speexresample/resample_sse.h +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) 2007-2008 Jean-Marc Valin - * Copyright (C) 2008 Thorvald Natvig - */ -/** - @file resample_sse.h - @brief Resampler functions (SSE version) -*/ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Neither the name of the Xiph.org Foundation nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include <xmmintrin.h> - -#define OVERRIDE_INNER_PRODUCT_SINGLE -static inline float inner_product_single(const float *a, const float *b, unsigned int len) -{ - int i; - float ret; - __m128 sum = _mm_setzero_ps(); - for (i=0;i<len;i+=8) - { - sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i))); - sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4))); - } - sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum)); - sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55)); - _mm_store_ss(&ret, sum); - return ret; -} - -#define OVERRIDE_INTERPOLATE_PRODUCT_SINGLE -static inline float interpolate_product_single(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) { - int i; - float ret; - __m128 sum = _mm_setzero_ps(); - __m128 f = _mm_loadu_ps(frac); - for(i=0;i<len;i+=2) - { - sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample))); - sum = _mm_add_ps(sum, _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample))); - } - sum = _mm_mul_ps(f, sum); - sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum)); - sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55)); - _mm_store_ss(&ret, sum); - return ret; -} - -#ifdef _USE_SSE2 -#include <emmintrin.h> -#define OVERRIDE_INNER_PRODUCT_DOUBLE - -static inline double inner_product_double(const float *a, const float *b, unsigned int len) -{ - int i; - double ret; - __m128d sum = _mm_setzero_pd(); - __m128 t; - for (i=0;i<len;i+=8) - { - t = _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i)); - sum = _mm_add_pd(sum, _mm_cvtps_pd(t)); - sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t))); - - t = _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4)); - sum = _mm_add_pd(sum, _mm_cvtps_pd(t)); - sum = _mm_add_pd(sum, _mm_cvtps_pd(_mm_movehl_ps(t, t))); - } - sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum)); - _mm_store_sd(&ret, sum); - return ret; -} - -#define OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE -static inline double interpolate_product_double(const float *a, const float *b, unsigned int len, const spx_uint32_t oversample, float *frac) { - int i; - double ret; - __m128d sum; - __m128d sum1 = _mm_setzero_pd(); - __m128d sum2 = _mm_setzero_pd(); - __m128 f = _mm_loadu_ps(frac); - __m128d f1 = _mm_cvtps_pd(f); - __m128d f2 = _mm_cvtps_pd(_mm_movehl_ps(f,f)); - __m128 t; - for(i=0;i<len;i+=2) - { - t = _mm_mul_ps(_mm_load1_ps(a+i), _mm_loadu_ps(b+i*oversample)); - sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t)); - sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t))); - - t = _mm_mul_ps(_mm_load1_ps(a+i+1), _mm_loadu_ps(b+(i+1)*oversample)); - sum1 = _mm_add_pd(sum1, _mm_cvtps_pd(t)); - sum2 = _mm_add_pd(sum2, _mm_cvtps_pd(_mm_movehl_ps(t, t))); - } - sum1 = _mm_mul_pd(f1, sum1); - sum2 = _mm_mul_pd(f2, sum2); - sum = _mm_add_pd(sum1, sum2); - sum = _mm_add_sd(sum, (__m128d) _mm_movehl_ps((__m128) sum, (__m128) sum)); - _mm_store_sd(&ret, sum); - return ret; -} - -#endif diff --git a/gst/speexresample/speex_resampler.h b/gst/speexresample/speex_resampler.h index 4e4a44ff..ad832c54 100644 --- a/gst/speexresample/speex_resampler.h +++ b/gst/speexresample/speex_resampler.h @@ -41,6 +41,8 @@ #ifdef OUTSIDE_SPEEX +#include <glib.h> + /********* WARNING: MENTAL SANITY ENDS HERE *************/ /* If the resampler is defined outside of Speex, we change the symbol names so that @@ -53,7 +55,7 @@ #define CAT_PREFIX2(a,b) a ## b #define CAT_PREFIX(a,b) CAT_PREFIX2(a, b) - + #define speex_resampler_init CAT_PREFIX(RANDOM_PREFIX,_resampler_init) #define speex_resampler_init_frac CAT_PREFIX(RANDOM_PREFIX,_resampler_init_frac) #define speex_resampler_destroy CAT_PREFIX(RANDOM_PREFIX,_resampler_destroy) @@ -81,20 +83,15 @@ #define spx_int32_t gint32 #define spx_uint16_t guint16 #define spx_uint32_t guint32 - + #else /* OUTSIDE_SPEEX */ -#ifdef _BUILD_SPEEX -# include "speex_types.h" -#else -# include <speex/speex_types.h> -#endif +#include "speex/speex_types.h" #endif /* OUTSIDE_SPEEX */ #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif #define SPEEX_RESAMPLER_QUALITY_MAX 10 @@ -103,19 +100,18 @@ extern "C" #define SPEEX_RESAMPLER_QUALITY_VOIP 3 #define SPEEX_RESAMPLER_QUALITY_DESKTOP 5 - enum - { - RESAMPLER_ERR_SUCCESS = 0, - RESAMPLER_ERR_ALLOC_FAILED = 1, - RESAMPLER_ERR_BAD_STATE = 2, - RESAMPLER_ERR_INVALID_ARG = 3, - RESAMPLER_ERR_PTR_OVERLAP = 4, - - RESAMPLER_ERR_MAX_ERROR - }; +enum { + RESAMPLER_ERR_SUCCESS = 0, + RESAMPLER_ERR_ALLOC_FAILED = 1, + RESAMPLER_ERR_BAD_STATE = 2, + RESAMPLER_ERR_INVALID_ARG = 3, + RESAMPLER_ERR_PTR_OVERLAP = 4, + + RESAMPLER_ERR_MAX_ERROR +}; - struct SpeexResamplerState_; - typedef struct SpeexResamplerState_ SpeexResamplerState; +struct SpeexResamplerState_; +typedef struct SpeexResamplerState_ SpeexResamplerState; /** Create a new resampler with integer input and output rates. * @param nb_channels Number of channels to be processed @@ -126,8 +122,11 @@ extern "C" * @return Newly created resampler state * @retval NULL Error: not enough memory */ - SpeexResamplerState *speex_resampler_init (spx_uint32_t nb_channels, - spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err); +SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, + spx_uint32_t in_rate, + spx_uint32_t out_rate, + int quality, + int *err); /** Create a new resampler with fractional input/output rates. The sampling * rate ratio is an arbitrary rational number with both the numerator and @@ -142,15 +141,18 @@ extern "C" * @return Newly created resampler state * @retval NULL Error: not enough memory */ - SpeexResamplerState *speex_resampler_init_frac (spx_uint32_t nb_channels, - spx_uint32_t ratio_num, - spx_uint32_t ratio_den, - spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err); +SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, + spx_uint32_t ratio_num, + spx_uint32_t ratio_den, + spx_uint32_t in_rate, + spx_uint32_t out_rate, + int quality, + int *err); /** Destroy a resampler state. * @param st Resampler state */ - void speex_resampler_destroy (SpeexResamplerState * st); +void speex_resampler_destroy(SpeexResamplerState *st); /** Resample a float array. The input and output buffers must *not* overlap. * @param st Resampler state @@ -162,17 +164,12 @@ 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 +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); /** Resample an int array. The input and output buffers must *not* overlap. * @param st Resampler state @@ -184,10 +181,12 @@ extern "C" * @param out Output buffer * @param out_len Size of the output buffer. Returns the number of samples written */ - int 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); +int 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); /** Resample an interleaved float array. The input and output buffers must *not* overlap. * @param st Resampler state @@ -198,15 +197,11 @@ 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 +int speex_resampler_process_interleaved_float(SpeexResamplerState *st, + const float *in, + spx_uint32_t *in_len, + float *out, + spx_uint32_t *out_len); /** Resample an interleaved int array. The input and output buffers must *not* overlap. * @param st Resampler state @@ -217,25 +212,29 @@ extern "C" * @param out_len Size of the output buffer. Returns the number of samples written. * This is all per-channel. */ - int speex_resampler_process_interleaved_int (SpeexResamplerState * st, - const spx_int16_t * in, - spx_uint32_t * in_len, spx_int16_t * out, spx_uint32_t * out_len); +int speex_resampler_process_interleaved_int(SpeexResamplerState *st, + const spx_int16_t *in, + spx_uint32_t *in_len, + spx_int16_t *out, + spx_uint32_t *out_len); /** Set (change) the input/output sampling rates (integer value). * @param st Resampler state * @param in_rate Input sampling rate (integer number of Hz). * @param out_rate Output sampling rate (integer number of Hz). */ - int speex_resampler_set_rate (SpeexResamplerState * st, - spx_uint32_t in_rate, spx_uint32_t out_rate); +int speex_resampler_set_rate(SpeexResamplerState *st, + spx_uint32_t in_rate, + spx_uint32_t out_rate); /** Get the current input/output sampling rates (integer value). * @param st Resampler state * @param in_rate Input sampling rate (integer number of Hz) copied. * @param out_rate Output sampling rate (integer number of Hz) copied. */ - void speex_resampler_get_rate (SpeexResamplerState * st, - spx_uint32_t * in_rate, spx_uint32_t * out_rate); +void speex_resampler_get_rate(SpeexResamplerState *st, + spx_uint32_t *in_rate, + spx_uint32_t *out_rate); /** Set (change) the input/output sampling rates and resampling ratio * (fractional values in Hz supported). @@ -245,9 +244,11 @@ extern "C" * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). */ - int speex_resampler_set_rate_frac (SpeexResamplerState * st, - spx_uint32_t ratio_num, - spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate); +int speex_resampler_set_rate_frac(SpeexResamplerState *st, + spx_uint32_t ratio_num, + spx_uint32_t ratio_den, + spx_uint32_t in_rate, + spx_uint32_t out_rate); /** Get the current resampling ratio. This will be reduced to the least * common denominator. @@ -255,60 +256,63 @@ extern "C" * @param ratio_num Numerator of the sampling rate ratio copied * @param ratio_den Denominator of the sampling rate ratio copied */ - void speex_resampler_get_ratio (SpeexResamplerState * st, - spx_uint32_t * ratio_num, spx_uint32_t * ratio_den); +void speex_resampler_get_ratio(SpeexResamplerState *st, + spx_uint32_t *ratio_num, + spx_uint32_t *ratio_den); /** Set (change) the conversion quality. * @param st Resampler state * @param quality Resampling quality between 0 and 10, where 0 has poor * quality and 10 has very high quality. */ - int speex_resampler_set_quality (SpeexResamplerState * st, int quality); +int speex_resampler_set_quality(SpeexResamplerState *st, + int quality); /** Get the conversion quality. * @param st Resampler state * @param quality Resampling quality between 0 and 10, where 0 has poor * quality and 10 has very high quality. */ - void speex_resampler_get_quality (SpeexResamplerState * st, int *quality); +void speex_resampler_get_quality(SpeexResamplerState *st, + int *quality); /** Set (change) the input stride. * @param st Resampler state * @param stride Input stride */ - void speex_resampler_set_input_stride (SpeexResamplerState * st, - spx_uint32_t stride); +void speex_resampler_set_input_stride(SpeexResamplerState *st, + spx_uint32_t stride); /** Get the input stride. * @param st Resampler state * @param stride Input stride copied */ - void speex_resampler_get_input_stride (SpeexResamplerState * st, - spx_uint32_t * stride); +void speex_resampler_get_input_stride(SpeexResamplerState *st, + spx_uint32_t *stride); /** Set (change) the output stride. * @param st Resampler state * @param stride Output stride */ - void speex_resampler_set_output_stride (SpeexResamplerState * st, - spx_uint32_t stride); +void speex_resampler_set_output_stride(SpeexResamplerState *st, + spx_uint32_t stride); /** Get the output stride. * @param st Resampler state copied * @param stride Output stride */ - void speex_resampler_get_output_stride (SpeexResamplerState * st, - spx_uint32_t * stride); +void speex_resampler_get_output_stride(SpeexResamplerState *st, + spx_uint32_t *stride); /** Get the latency in input samples introduced by the resampler. * @param st Resampler state */ - int speex_resampler_get_input_latency (SpeexResamplerState * st); +int speex_resampler_get_input_latency(SpeexResamplerState *st); /** Get the latency in output samples introduced by the resampler. * @param st Resampler state */ - int speex_resampler_get_output_latency (SpeexResamplerState * st); +int speex_resampler_get_output_latency(SpeexResamplerState *st); /** Make sure that the first samples to go out of the resamplers don't have * leading zeros. This is only useful before starting to use a newly created @@ -318,18 +322,18 @@ extern "C" * is the same for the first frame). * @param st Resampler state */ - int speex_resampler_skip_zeros (SpeexResamplerState * st); +int speex_resampler_skip_zeros(SpeexResamplerState *st); /** Reset a resampler so a new (unrelated) stream can be processed. * @param st Resampler state */ - int speex_resampler_reset_mem (SpeexResamplerState * st); +int speex_resampler_reset_mem(SpeexResamplerState *st); /** Returns the English meaning for an error code * @param err Error code * @return English string */ - const char *speex_resampler_strerror (int err); +const char *speex_resampler_strerror(int err); #ifdef __cplusplus } diff --git a/gst/speexresample/speex_resampler_double.c b/gst/speexresample/speex_resampler_double.c deleted file mode 100644 index e5a25714..00000000 --- a/gst/speexresample/speex_resampler_double.c +++ /dev/null @@ -1,25 +0,0 @@ -/* GStreamer - * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk> - * - * 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_float.c b/gst/speexresample/speex_resampler_float.c index f13f60c5..281e52d3 100644 --- a/gst/speexresample/speex_resampler_float.c +++ b/gst/speexresample/speex_resampler_float.c @@ -1,5 +1,5 @@ /* GStreamer - * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * 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 diff --git a/gst/speexresample/speex_resampler_int.c b/gst/speexresample/speex_resampler_int.c index 6b858604..c992f0a6 100644 --- a/gst/speexresample/speex_resampler_int.c +++ b/gst/speexresample/speex_resampler_int.c @@ -1,5 +1,5 @@ /* GStreamer - * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * 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 diff --git a/gst/speexresample/speex_resampler_wrapper.h b/gst/speexresample/speex_resampler_wrapper.h index 36d444f8..6d7c17d0 100644 --- a/gst/speexresample/speex_resampler_wrapper.h +++ b/gst/speexresample/speex_resampler_wrapper.h @@ -1,5 +1,5 @@ /* GStreamer - * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * 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 @@ -39,123 +39,48 @@ 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); - unsigned int width; -} SpeexResampleFuncs; - 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 guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len); -int resample_float_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_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, - 32 -}; - -SpeexResamplerState *resample_double_resampler_init (guint32 nb_channels, +SpeexResamplerState *resample_int_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, - 64 -}; +#define resample_resampler_destroy resample_int_resampler_destroy +void resample_resampler_destroy (SpeexResamplerState * st); -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_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); + +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, 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); -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, - 16 -}; +#define resample_resampler_strerror resample_int_resampler_strerror +const char *resample_resampler_strerror (gint err); #endif /* __SPEEX_RESAMPLER_WRAPPER_H__ */ |