<p>George Joseph <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/12788">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved; Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">codec_resample: Upgrade speex_resample to fix up-sampling bug<br><br>ASTERISK-28511 #close<br><br>Change-Id: Idd07bf341e89ac999c7f5701d9b72b8a9cb11e82<br>---<br>M codecs/Makefile<br>M codecs/speex/arch.h<br>M codecs/speex/fixed_generic.h<br>M codecs/speex/resample.c<br>M codecs/speex/speex_resampler.h<br>5 files changed, 218 insertions(+), 139 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/codecs/Makefile b/codecs/Makefile</span><br><span>index 86a7dec..535bf1b 100644</span><br><span>--- a/codecs/Makefile</span><br><span>+++ b/codecs/Makefile</span><br><span>@@ -90,4 +90,4 @@</span><br><span> endif</span><br><span> </span><br><span> $(call MOD_ADD_C,codec_resample,speex/resample.c)</span><br><span style="color: hsl(0, 100%, 40%);">-speex/resample.o: _ASTCFLAGS+=$(SPEEX_RESAMPLE_CFLAGS)</span><br><span style="color: hsl(120, 100%, 40%);">+speex/resample.o: _ASTCFLAGS+=$(SPEEX_RESAMPLE_CFLAGS) -DOUTSIDE_SPEEX -DEXPORT=</span><br><span>diff --git a/codecs/speex/arch.h b/codecs/speex/arch.h</span><br><span>index 435befc..fc51d8f 100644</span><br><span>--- a/codecs/speex/arch.h</span><br><span>+++ b/codecs/speex/arch.h</span><br><span>@@ -35,14 +35,6 @@</span><br><span> #ifndef ARCH_H</span><br><span> #define ARCH_H</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#ifndef SPEEX_VERSION</span><br><span style="color: hsl(0, 100%, 40%);">-#define SPEEX_MAJOR_VERSION 1         /**< Major Speex version. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define SPEEX_MINOR_VERSION 1         /**< Minor Speex version. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define SPEEX_MICRO_VERSION 15        /**< Micro Speex version. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define SPEEX_EXTRA_VERSION ""        /**< Extra Speex version. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define SPEEX_VERSION "speex-1.2beta3"  /**< Speex version string. */</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> #define FIXED_POINT</span><br><span> </span><br><span> /* A couple test to catch stupid option combinations */</span><br><span>@@ -77,7 +69,7 @@</span><br><span> #endif</span><br><span> </span><br><span> #ifndef OUTSIDE_SPEEX</span><br><span style="color: hsl(0, 100%, 40%);">-#include "speex/speex_types.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "speex/speexdsp_types.h"</span><br><span> #endif</span><br><span> </span><br><span> #define ABS(x) ((x) < 0 ? (-(x)) : (x))      /**< Absolute integer value. */</span><br><span>@@ -91,7 +83,7 @@</span><br><span> #ifdef FIXED_POINT</span><br><span> </span><br><span> typedef spx_int16_t spx_word16_t;</span><br><span style="color: hsl(0, 100%, 40%);">-typedef spx_int32_t   spx_word32_t;</span><br><span style="color: hsl(120, 100%, 40%);">+typedef spx_int32_t spx_word32_t;</span><br><span> typedef spx_word32_t spx_mem_t;</span><br><span> typedef spx_word16_t spx_coef_t;</span><br><span> typedef spx_word16_t spx_lsp_t;</span><br><span>@@ -173,6 +165,7 @@</span><br><span> #define VSHR32(a,shift) (a)</span><br><span> #define SATURATE16(x,a) (x)</span><br><span> #define SATURATE32(x,a) (x)</span><br><span style="color: hsl(120, 100%, 40%);">+#define SATURATE32PSHR(x,shift,a) (x)</span><br><span> </span><br><span> #define PSHR(a,shift)       (a)</span><br><span> #define SHR(a,shift)       (a)</span><br><span>diff --git a/codecs/speex/fixed_generic.h b/codecs/speex/fixed_generic.h</span><br><span>index 0b21918..12d27aa 100644</span><br><span>--- a/codecs/speex/fixed_generic.h</span><br><span>+++ b/codecs/speex/fixed_generic.h</span><br><span>@@ -52,6 +52,10 @@</span><br><span> #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))</span><br><span> #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define SATURATE32PSHR(x,shift,a) (((x)>=(SHL32(a,shift))) ? (a) : \</span><br><span style="color: hsl(120, 100%, 40%);">+                                   (x)<=-(SHL32(a,shift)) ? -(a) : \</span><br><span style="color: hsl(120, 100%, 40%);">+                                   (PSHR32(x, shift)))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define SHR(a,shift) ((a) >> (shift))</span><br><span> #define SHL(a,shift) ((spx_word32_t)(a) << (shift))</span><br><span> #define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))</span><br><span>diff --git a/codecs/speex/resample.c b/codecs/speex/resample.c</span><br><span>index 0797352..4940a64 100644</span><br><span>--- a/codecs/speex/resample.c</span><br><span>+++ b/codecs/speex/resample.c</span><br><span>@@ -61,18 +61,26 @@</span><br><span> #include "config.h"</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef OUTSIDE_SPEEX</span><br><span> #include <stdlib.h></span><br><span> static void *speex_alloc (int size) {return calloc(size,1);}</span><br><span> static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}</span><br><span> static void speex_free (void *ptr) {free(ptr);}</span><br><span> #include "speex_resampler.h"</span><br><span> #include "arch.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#else /* OUTSIDE_SPEEX */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "speex/speex_resampler.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "arch.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "os_support.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* OUTSIDE_SPEEX */</span><br><span> </span><br><span> #include "stack_alloc.h"</span><br><span> #include <math.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <limits.h></span><br><span> </span><br><span> #ifndef M_PI</span><br><span style="color: hsl(0, 100%, 40%);">-#define M_PI 3.14159263</span><br><span style="color: hsl(120, 100%, 40%);">+#define M_PI 3.14159265358979323846</span><br><span> #endif</span><br><span> </span><br><span> #ifdef FIXED_POINT</span><br><span>@@ -92,6 +100,10 @@</span><br><span> #include "resample_sse.h"</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef _USE_NEON</span><br><span style="color: hsl(120, 100%, 40%);">+#include "resample_neon.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Numer of elements to allocate on the stack */</span><br><span> #ifdef VAR_ARRAYS</span><br><span> #define FIXED_STACK_ALLOC 8192</span><br><span>@@ -133,7 +145,7 @@</span><br><span>    int    out_stride;</span><br><span> } ;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static double kaiser12_table[68] = {</span><br><span style="color: hsl(120, 100%, 40%);">+static const double kaiser12_table[68] = {</span><br><span>    0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,</span><br><span>    0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,</span><br><span>    0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,</span><br><span>@@ -147,7 +159,7 @@</span><br><span>    0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,</span><br><span>    0.00001000, 0.00000000};</span><br><span> /*</span><br><span style="color: hsl(0, 100%, 40%);">-static double kaiser12_table[36] = {</span><br><span style="color: hsl(120, 100%, 40%);">+static const double kaiser12_table[36] = {</span><br><span>    0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,</span><br><span>    0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,</span><br><span>    0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,</span><br><span>@@ -155,7 +167,7 @@</span><br><span>    0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,</span><br><span>    0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-static double kaiser10_table[36] = {</span><br><span style="color: hsl(120, 100%, 40%);">+static const double kaiser10_table[36] = {</span><br><span>    0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,</span><br><span>    0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,</span><br><span>    0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,</span><br><span>@@ -163,7 +175,7 @@</span><br><span>    0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,</span><br><span>    0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000};</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static double kaiser8_table[36] = {</span><br><span style="color: hsl(120, 100%, 40%);">+static const double kaiser8_table[36] = {</span><br><span>    0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,</span><br><span>    0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,</span><br><span>    0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,</span><br><span>@@ -171,7 +183,7 @@</span><br><span>    0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,</span><br><span>    0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static double kaiser6_table[36] = {</span><br><span style="color: hsl(120, 100%, 40%);">+static const double kaiser6_table[36] = {</span><br><span>    0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,</span><br><span>    0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,</span><br><span>    0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,</span><br><span>@@ -180,19 +192,19 @@</span><br><span>    0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000};</span><br><span> </span><br><span> struct FuncDef {</span><br><span style="color: hsl(0, 100%, 40%);">-   double *table;</span><br><span style="color: hsl(120, 100%, 40%);">+   const double *table;</span><br><span>    int oversample;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static struct FuncDef _KAISER12 = {kaiser12_table, 64};</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct FuncDef _KAISER12 = {kaiser12_table, 64};</span><br><span> #define KAISER12 (&_KAISER12)</span><br><span> /*static struct FuncDef _KAISER12 = {kaiser12_table, 32};</span><br><span> #define KAISER12 (&_KAISER12)*/</span><br><span style="color: hsl(0, 100%, 40%);">-static struct FuncDef _KAISER10 = {kaiser10_table, 32};</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct FuncDef _KAISER10 = {kaiser10_table, 32};</span><br><span> #define KAISER10 (&_KAISER10)</span><br><span style="color: hsl(0, 100%, 40%);">-static struct FuncDef _KAISER8 = {kaiser8_table, 32};</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct FuncDef _KAISER8 = {kaiser8_table, 32};</span><br><span> #define KAISER8 (&_KAISER8)</span><br><span style="color: hsl(0, 100%, 40%);">-static struct FuncDef _KAISER6 = {kaiser6_table, 32};</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct FuncDef _KAISER6 = {kaiser6_table, 32};</span><br><span> #define KAISER6 (&_KAISER6)</span><br><span> </span><br><span> struct QualityMapping {</span><br><span>@@ -200,7 +212,7 @@</span><br><span>    int oversample;</span><br><span>    float downsample_bandwidth;</span><br><span>    float upsample_bandwidth;</span><br><span style="color: hsl(0, 100%, 40%);">-   struct FuncDef *window_func;</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct FuncDef *window_func;</span><br><span> };</span><br><span> </span><br><span> </span><br><span>@@ -227,7 +239,7 @@</span><br><span>    {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */</span><br><span> };</span><br><span> /*8,24,40,56,80,104,128,160,200,256,320*/</span><br><span style="color: hsl(0, 100%, 40%);">-static double compute_func(float x, struct FuncDef *func)</span><br><span style="color: hsl(120, 100%, 40%);">+static double compute_func(float x, const struct FuncDef *func)</span><br><span> {</span><br><span>    float y, frac;</span><br><span>    double interp[4];</span><br><span>@@ -262,7 +274,7 @@</span><br><span> </span><br><span> #ifdef FIXED_POINT</span><br><span> /* The slow way of computing a sinc for the table. Should improve that some day */</span><br><span style="color: hsl(0, 100%, 40%);">-static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)</span><br><span style="color: hsl(120, 100%, 40%);">+static spx_word16_t sinc(float cutoff, float x, int N, const struct FuncDef *window_func)</span><br><span> {</span><br><span>    /*fprintf (stderr, "%f ", x);*/</span><br><span>    float xx = x * cutoff;</span><br><span>@@ -275,7 +287,7 @@</span><br><span> }</span><br><span> #else</span><br><span> /* The slow way of computing a sinc for the table. Should improve that some day */</span><br><span style="color: hsl(0, 100%, 40%);">-static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)</span><br><span style="color: hsl(120, 100%, 40%);">+static spx_word16_t sinc(float cutoff, float x, int N, const struct FuncDef *window_func)</span><br><span> {</span><br><span>    /*fprintf (stderr, "%f ", x);*/</span><br><span>    float xx = x * cutoff;</span><br><span>@@ -330,28 +342,35 @@</span><br><span>    const int frac_advance = st->frac_advance;</span><br><span>    const spx_uint32_t den_rate = st->den_rate;</span><br><span>    spx_word32_t sum;</span><br><span style="color: hsl(0, 100%, 40%);">-   int j;</span><br><span> </span><br><span>    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))</span><br><span>    {</span><br><span style="color: hsl(0, 100%, 40%);">-      const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];</span><br><span style="color: hsl(120, 100%, 40%);">+      const spx_word16_t *sinct = & sinc_table[samp_frac_num*N];</span><br><span>       const spx_word16_t *iptr = & in[last_sample];</span><br><span> </span><br><span> #ifndef OVERRIDE_INNER_PRODUCT_SINGLE</span><br><span style="color: hsl(0, 100%, 40%);">-      float accum[4] = {0,0,0,0};</span><br><span style="color: hsl(120, 100%, 40%);">+      int j;</span><br><span style="color: hsl(120, 100%, 40%);">+      sum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      for(j=0;j<N;j++) sum += MULT16_16(sinct[j], iptr[j]);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*    This code is slower on most DSPs which have only 2 accumulators.</span><br><span style="color: hsl(120, 100%, 40%);">+      Plus this this forces truncation to 32 bits and you lose the HW guard bits.</span><br><span style="color: hsl(120, 100%, 40%);">+      I think we can trust the compiler and let it vectorize and/or unroll itself.</span><br><span style="color: hsl(120, 100%, 40%);">+      spx_word32_t accum[4] = {0,0,0,0};</span><br><span>       for(j=0;j<N;j+=4) {</span><br><span style="color: hsl(0, 100%, 40%);">-        accum[0] += sinc[j]*iptr[j];</span><br><span style="color: hsl(0, 100%, 40%);">-        accum[1] += sinc[j+1]*iptr[j+1];</span><br><span style="color: hsl(0, 100%, 40%);">-        accum[2] += sinc[j+2]*iptr[j+2];</span><br><span style="color: hsl(0, 100%, 40%);">-        accum[3] += sinc[j+3]*iptr[j+3];</span><br><span style="color: hsl(120, 100%, 40%);">+        accum[0] += MULT16_16(sinct[j], iptr[j]);</span><br><span style="color: hsl(120, 100%, 40%);">+        accum[1] += MULT16_16(sinct[j+1], iptr[j+1]);</span><br><span style="color: hsl(120, 100%, 40%);">+        accum[2] += MULT16_16(sinct[j+2], iptr[j+2]);</span><br><span style="color: hsl(120, 100%, 40%);">+        accum[3] += MULT16_16(sinct[j+3], iptr[j+3]);</span><br><span>       }</span><br><span>       sum = accum[0] + accum[1] + accum[2] + accum[3];</span><br><span style="color: hsl(120, 100%, 40%);">+*/</span><br><span style="color: hsl(120, 100%, 40%);">+      sum = SATURATE32PSHR(sum, 15, 32767);</span><br><span> #else</span><br><span style="color: hsl(0, 100%, 40%);">-      sum = inner_product_single(sinc, iptr, N);</span><br><span style="color: hsl(120, 100%, 40%);">+      sum = inner_product_single(sinct, iptr, N);</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      out[out_stride * out_sample++] = PSHR32(sum, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+      out[out_stride * out_sample++] = sum;</span><br><span>       last_sample += int_advance;</span><br><span>       samp_frac_num += frac_advance;</span><br><span>       if (samp_frac_num >= den_rate)</span><br><span>@@ -381,25 +400,25 @@</span><br><span>    const int frac_advance = st->frac_advance;</span><br><span>    const spx_uint32_t den_rate = st->den_rate;</span><br><span>    double sum;</span><br><span style="color: hsl(0, 100%, 40%);">-   int j;</span><br><span> </span><br><span>    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))</span><br><span>    {</span><br><span style="color: hsl(0, 100%, 40%);">-      const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];</span><br><span style="color: hsl(120, 100%, 40%);">+      const spx_word16_t *sinct = & sinc_table[samp_frac_num*N];</span><br><span>       const spx_word16_t *iptr = & in[last_sample];</span><br><span> </span><br><span> #ifndef OVERRIDE_INNER_PRODUCT_DOUBLE</span><br><span style="color: hsl(120, 100%, 40%);">+      int j;</span><br><span>       double accum[4] = {0,0,0,0};</span><br><span> </span><br><span>       for(j=0;j<N;j+=4) {</span><br><span style="color: hsl(0, 100%, 40%);">-        accum[0] += sinc[j]*iptr[j];</span><br><span style="color: hsl(0, 100%, 40%);">-        accum[1] += sinc[j+1]*iptr[j+1];</span><br><span style="color: hsl(0, 100%, 40%);">-        accum[2] += sinc[j+2]*iptr[j+2];</span><br><span style="color: hsl(0, 100%, 40%);">-        accum[3] += sinc[j+3]*iptr[j+3];</span><br><span style="color: hsl(120, 100%, 40%);">+        accum[0] += sinct[j]*iptr[j];</span><br><span style="color: hsl(120, 100%, 40%);">+        accum[1] += sinct[j+1]*iptr[j+1];</span><br><span style="color: hsl(120, 100%, 40%);">+        accum[2] += sinct[j+2]*iptr[j+2];</span><br><span style="color: hsl(120, 100%, 40%);">+        accum[3] += sinct[j+3]*iptr[j+3];</span><br><span>       }</span><br><span>       sum = accum[0] + accum[1] + accum[2] + accum[3];</span><br><span> #else</span><br><span style="color: hsl(0, 100%, 40%);">-      sum = inner_product_double(sinc, iptr, N);</span><br><span style="color: hsl(120, 100%, 40%);">+      sum = inner_product_double(sinct, iptr, N);</span><br><span> #endif</span><br><span> </span><br><span>       out[out_stride * out_sample++] = PSHR32(sum, 15);</span><br><span>@@ -428,7 +447,6 @@</span><br><span>    const int int_advance = st->int_advance;</span><br><span>    const int frac_advance = st->frac_advance;</span><br><span>    const spx_uint32_t den_rate = st->den_rate;</span><br><span style="color: hsl(0, 100%, 40%);">-   int j;</span><br><span>    spx_word32_t sum;</span><br><span> </span><br><span>    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))</span><br><span>@@ -445,6 +463,7 @@</span><br><span> </span><br><span> </span><br><span> #ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE</span><br><span style="color: hsl(120, 100%, 40%);">+      int j;</span><br><span>       spx_word32_t accum[4] = {0,0,0,0};</span><br><span> </span><br><span>       for(j=0;j<N;j++) {</span><br><span>@@ -456,13 +475,14 @@</span><br><span>       }</span><br><span> </span><br><span>       cubic_coef(frac, interp);</span><br><span style="color: hsl(0, 100%, 40%);">-      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]);</span><br><span style="color: hsl(120, 100%, 40%);">+      sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1));</span><br><span style="color: hsl(120, 100%, 40%);">+      sum = SATURATE32PSHR(sum, 15, 32767);</span><br><span> #else</span><br><span>       cubic_coef(frac, interp);</span><br><span>       sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      out[out_stride * out_sample++] = PSHR32(sum,15);</span><br><span style="color: hsl(120, 100%, 40%);">+      out[out_stride * out_sample++] = sum;</span><br><span>       last_sample += int_advance;</span><br><span>       samp_frac_num += frac_advance;</span><br><span>       if (samp_frac_num >= den_rate)</span><br><span>@@ -490,7 +510,6 @@</span><br><span>    const int int_advance = st->int_advance;</span><br><span>    const int frac_advance = st->frac_advance;</span><br><span>    const spx_uint32_t den_rate = st->den_rate;</span><br><span style="color: hsl(0, 100%, 40%);">-   int j;</span><br><span>    spx_word32_t sum;</span><br><span> </span><br><span>    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))</span><br><span>@@ -507,6 +526,7 @@</span><br><span> </span><br><span> </span><br><span> #ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE</span><br><span style="color: hsl(120, 100%, 40%);">+      int j;</span><br><span>       double accum[4] = {0,0,0,0};</span><br><span> </span><br><span>       for(j=0;j<N;j++) {</span><br><span>@@ -540,11 +560,47 @@</span><br><span> }</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void update_filter(SpeexResamplerState *st)</span><br><span style="color: hsl(120, 100%, 40%);">+/* This resampler is used to produce zero output in situations where memory</span><br><span style="color: hsl(120, 100%, 40%);">+   for the filter could not be allocated.  The expected numbers of input and</span><br><span style="color: hsl(120, 100%, 40%);">+   output samples are still processed so that callers failing to check error</span><br><span style="color: hsl(120, 100%, 40%);">+   codes are not surprised, possibly getting into infinite loops. */</span><br><span style="color: hsl(120, 100%, 40%);">+static int resampler_basic_zero(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)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   spx_uint32_t old_length;</span><br><span style="color: hsl(120, 100%, 40%);">+   int out_sample = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   int last_sample = st->last_sample[channel_index];</span><br><span style="color: hsl(120, 100%, 40%);">+   spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];</span><br><span style="color: hsl(120, 100%, 40%);">+   const int out_stride = st->out_stride;</span><br><span style="color: hsl(120, 100%, 40%);">+   const int int_advance = st->int_advance;</span><br><span style="color: hsl(120, 100%, 40%);">+   const int frac_advance = st->frac_advance;</span><br><span style="color: hsl(120, 100%, 40%);">+   const spx_uint32_t den_rate = st->den_rate;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   old_length = st->filt_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))</span><br><span style="color: hsl(120, 100%, 40%);">+   {</span><br><span style="color: hsl(120, 100%, 40%);">+      out[out_stride * out_sample++] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      last_sample += int_advance;</span><br><span style="color: hsl(120, 100%, 40%);">+      samp_frac_num += frac_advance;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (samp_frac_num >= den_rate)</span><br><span style="color: hsl(120, 100%, 40%);">+      {</span><br><span style="color: hsl(120, 100%, 40%);">+         samp_frac_num -= den_rate;</span><br><span style="color: hsl(120, 100%, 40%);">+         last_sample++;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   st->last_sample[channel_index] = last_sample;</span><br><span style="color: hsl(120, 100%, 40%);">+   st->samp_frac_num[channel_index] = samp_frac_num;</span><br><span style="color: hsl(120, 100%, 40%);">+   return out_sample;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int update_filter(SpeexResamplerState *st)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   spx_uint32_t old_length = st->filt_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   spx_uint32_t old_alloc_size = st->mem_alloc_size;</span><br><span style="color: hsl(120, 100%, 40%);">+   int use_direct;</span><br><span style="color: hsl(120, 100%, 40%);">+   spx_uint32_t min_sinc_table_length;</span><br><span style="color: hsl(120, 100%, 40%);">+   spx_uint32_t min_alloc_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   st->int_advance = st->num_rate/st->den_rate;</span><br><span style="color: hsl(120, 100%, 40%);">+   st->frac_advance = st->num_rate%st->den_rate;</span><br><span>    st->oversample = quality_map[st->quality].oversample;</span><br><span>    st->filt_len = quality_map[st->quality].base_length;</span><br><span> </span><br><span>@@ -554,8 +610,8 @@</span><br><span>       st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;</span><br><span>       /* FIXME: divide the numerator and denominator by a certain amount if they're too large */</span><br><span>       st->filt_len = st->filt_len*st->num_rate / st->den_rate;</span><br><span style="color: hsl(0, 100%, 40%);">-      /* Round down to make sure we have a multiple of 4 */</span><br><span style="color: hsl(0, 100%, 40%);">-      st->filt_len &= (~0x3);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Round up to make sure we have a multiple of 8 for SSE */</span><br><span style="color: hsl(120, 100%, 40%);">+      st->filt_len = ((st->filt_len-1)&(~0x7))+8;</span><br><span>       if (2*st->den_rate < st->num_rate)</span><br><span>          st->oversample >>= 1;</span><br><span>       if (4*st->den_rate < st->num_rate)</span><br><span>@@ -572,16 +628,35 @@</span><br><span>    }</span><br><span> </span><br><span>    /* Choose the resampling type that requires the least amount of memory */</span><br><span style="color: hsl(0, 100%, 40%);">-   if (st->den_rate <= st->oversample)</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef RESAMPLE_FULL_SINC_TABLE</span><br><span style="color: hsl(120, 100%, 40%);">+   use_direct = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+   if (INT_MAX/sizeof(spx_word16_t)/st->den_rate < st->filt_len)</span><br><span style="color: hsl(120, 100%, 40%);">+      goto fail;</span><br><span style="color: hsl(120, 100%, 40%);">+#else</span><br><span style="color: hsl(120, 100%, 40%);">+   use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8</span><br><span style="color: hsl(120, 100%, 40%);">+                && INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+   if (use_direct)</span><br><span style="color: hsl(120, 100%, 40%);">+   {</span><br><span style="color: hsl(120, 100%, 40%);">+      min_sinc_table_length = st->filt_len*st->den_rate;</span><br><span style="color: hsl(120, 100%, 40%);">+   } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      if ((INT_MAX/sizeof(spx_word16_t)-8)/st->oversample < st->filt_len)</span><br><span style="color: hsl(120, 100%, 40%);">+         goto fail;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      min_sinc_table_length = st->filt_len*st->oversample+8;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+   if (st->sinc_table_length < min_sinc_table_length)</span><br><span style="color: hsl(120, 100%, 40%);">+   {</span><br><span style="color: hsl(120, 100%, 40%);">+      spx_word16_t *sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,min_sinc_table_length*sizeof(spx_word16_t));</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!sinc_table)</span><br><span style="color: hsl(120, 100%, 40%);">+         goto fail;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      st->sinc_table = sinc_table;</span><br><span style="color: hsl(120, 100%, 40%);">+      st->sinc_table_length = min_sinc_table_length;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+   if (use_direct)</span><br><span>    {</span><br><span>       spx_uint32_t i;</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!st->sinc_table)</span><br><span style="color: hsl(0, 100%, 40%);">-         st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t));</span><br><span style="color: hsl(0, 100%, 40%);">-      else if (st->sinc_table_length < st->filt_len*st->den_rate)</span><br><span style="color: hsl(0, 100%, 40%);">-      {</span><br><span style="color: hsl(0, 100%, 40%);">-         st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t));</span><br><span style="color: hsl(0, 100%, 40%);">-         st->sinc_table_length = st->filt_len*st->den_rate;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span>       for (i=0;i<st->den_rate;i++)</span><br><span>       {</span><br><span>          spx_int32_t j;</span><br><span>@@ -601,13 +676,6 @@</span><br><span>       /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/</span><br><span>    } else {</span><br><span>       spx_int32_t i;</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!st->sinc_table)</span><br><span style="color: hsl(0, 100%, 40%);">-         st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t));</span><br><span style="color: hsl(0, 100%, 40%);">-      else if (st->sinc_table_length < st->filt_len*st->oversample+8)</span><br><span style="color: hsl(0, 100%, 40%);">-      {</span><br><span style="color: hsl(0, 100%, 40%);">-         st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t));</span><br><span style="color: hsl(0, 100%, 40%);">-         st->sinc_table_length = st->filt_len*st->oversample+8;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span>       for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++)</span><br><span>          st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func);</span><br><span> #ifdef FIXED_POINT</span><br><span>@@ -620,43 +688,39 @@</span><br><span> #endif</span><br><span>       /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/</span><br><span>    }</span><br><span style="color: hsl(0, 100%, 40%);">-   st->int_advance = st->num_rate/st->den_rate;</span><br><span style="color: hsl(0, 100%, 40%);">-   st->frac_advance = st->num_rate%st->den_rate;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> </span><br><span>    /* Here's the place where we update the filter memory to take into account</span><br><span>       the change in filter length. It's probably the messiest part of the code</span><br><span>       due to handling of lots of corner cases. */</span><br><span style="color: hsl(0, 100%, 40%);">-   if (!st->mem)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Adding buffer_size to filt_len won't overflow here because filt_len</span><br><span style="color: hsl(120, 100%, 40%);">+      could be multiplied by sizeof(spx_word16_t) above. */</span><br><span style="color: hsl(120, 100%, 40%);">+   min_alloc_size = st->filt_len-1 + st->buffer_size;</span><br><span style="color: hsl(120, 100%, 40%);">+   if (min_alloc_size > st->mem_alloc_size)</span><br><span style="color: hsl(120, 100%, 40%);">+   {</span><br><span style="color: hsl(120, 100%, 40%);">+      spx_word16_t *mem;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (INT_MAX/sizeof(spx_word16_t)/st->nb_channels < min_alloc_size)</span><br><span style="color: hsl(120, 100%, 40%);">+          goto fail;</span><br><span style="color: hsl(120, 100%, 40%);">+      else if (!(mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*min_alloc_size * sizeof(*mem))))</span><br><span style="color: hsl(120, 100%, 40%);">+          goto fail;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      st->mem = mem;</span><br><span style="color: hsl(120, 100%, 40%);">+      st->mem_alloc_size = min_alloc_size;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!st->started)</span><br><span>    {</span><br><span>       spx_uint32_t i;</span><br><span style="color: hsl(0, 100%, 40%);">-      st->mem_alloc_size = st->filt_len-1 + st->buffer_size;</span><br><span style="color: hsl(0, 100%, 40%);">-      st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));</span><br><span style="color: hsl(0, 100%, 40%);">-      for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)</span><br><span style="color: hsl(0, 100%, 40%);">-         st->mem[i] = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-      /*speex_warning("init filter");*/</span><br><span style="color: hsl(0, 100%, 40%);">-   } else if (!st->started)</span><br><span style="color: hsl(0, 100%, 40%);">-   {</span><br><span style="color: hsl(0, 100%, 40%);">-      spx_uint32_t i;</span><br><span style="color: hsl(0, 100%, 40%);">-      st->mem_alloc_size = st->filt_len-1 + st->buffer_size;</span><br><span style="color: hsl(0, 100%, 40%);">-      st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));</span><br><span>       for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)</span><br><span>          st->mem[i] = 0;</span><br><span>       /*speex_warning("reinit filter");*/</span><br><span>    } else if (st->filt_len > old_length)</span><br><span>    {</span><br><span style="color: hsl(0, 100%, 40%);">-      spx_int32_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+      spx_uint32_t i;</span><br><span>       /* Increase the filter length */</span><br><span>       /*speex_warning("increase filter size");*/</span><br><span style="color: hsl(0, 100%, 40%);">-      int old_alloc_size = st->mem_alloc_size;</span><br><span style="color: hsl(0, 100%, 40%);">-      if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size)</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i=st->nb_channels;i--;)</span><br><span>       {</span><br><span style="color: hsl(0, 100%, 40%);">-         st->mem_alloc_size = st->filt_len-1 + st->buffer_size;</span><br><span style="color: hsl(0, 100%, 40%);">-         st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-      for (i=st->nb_channels-1;i>=0;i--)</span><br><span style="color: hsl(0, 100%, 40%);">-      {</span><br><span style="color: hsl(0, 100%, 40%);">-         spx_int32_t j;</span><br><span style="color: hsl(120, 100%, 40%);">+         spx_uint32_t j;</span><br><span>          spx_uint32_t olen = old_length;</span><br><span>          /*if (st->magic_samples[i])*/</span><br><span>          {</span><br><span>@@ -664,7 +728,7 @@</span><br><span> </span><br><span>             /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */</span><br><span>             olen = old_length + 2*st->magic_samples[i];</span><br><span style="color: hsl(0, 100%, 40%);">-            for (j=old_length-2+st->magic_samples[i];j>=0;j--)</span><br><span style="color: hsl(120, 100%, 40%);">+            for (j=old_length-1+st->magic_samples[i];j--;)</span><br><span>                st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j];</span><br><span>             for (j=0;j<st->magic_samples[i];j++)</span><br><span>                st->mem[i*st->mem_alloc_size+j] = 0;</span><br><span>@@ -705,18 +769,28 @@</span><br><span>          st->magic_samples[i] += old_magic;</span><br><span>       }</span><br><span>    }</span><br><span style="color: hsl(120, 100%, 40%);">+   return RESAMPLER_ERR_SUCCESS;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+fail:</span><br><span style="color: hsl(120, 100%, 40%);">+   st->resampler_ptr = resampler_basic_zero;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* st->mem may still contain consumed input samples for the filter.</span><br><span style="color: hsl(120, 100%, 40%);">+      Restore filt_len so that filt_len - 1 still points to the position after</span><br><span style="color: hsl(120, 100%, 40%);">+      the last of these samples. */</span><br><span style="color: hsl(120, 100%, 40%);">+   st->filt_len = old_length;</span><br><span style="color: hsl(120, 100%, 40%);">+   return RESAMPLER_ERR_ALLOC_FAILED;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)</span><br><span> {</span><br><span>    return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- 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)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT 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)</span><br><span> {</span><br><span>    spx_uint32_t i;</span><br><span>    SpeexResamplerState *st;</span><br><span style="color: hsl(120, 100%, 40%);">+   int filter_err;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    if (quality > 10 || quality < 0)</span><br><span>    {</span><br><span>       if (err)</span><br><span>@@ -742,16 +816,12 @@</span><br><span>    st->in_stride = 1;</span><br><span>    st->out_stride = 1;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#ifdef FIXED_POINT</span><br><span>    st->buffer_size = 160;</span><br><span style="color: hsl(0, 100%, 40%);">-#else</span><br><span style="color: hsl(0, 100%, 40%);">-   st->buffer_size = 160;</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span> </span><br><span>    /* Per channel data */</span><br><span style="color: hsl(0, 100%, 40%);">-   st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));</span><br><span style="color: hsl(0, 100%, 40%);">-   st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));</span><br><span style="color: hsl(0, 100%, 40%);">-   st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));</span><br><span style="color: hsl(120, 100%, 40%);">+   st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(spx_int32_t));</span><br><span style="color: hsl(120, 100%, 40%);">+   st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t));</span><br><span style="color: hsl(120, 100%, 40%);">+   st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t));</span><br><span>    for (i=0;i<nb_channels;i++)</span><br><span>    {</span><br><span>       st->last_sample[i] = 0;</span><br><span>@@ -762,17 +832,21 @@</span><br><span>    speex_resampler_set_quality(st, quality);</span><br><span>    speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   update_filter(st);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   st->initialised = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+   filter_err = update_filter(st);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (filter_err == RESAMPLER_ERR_SUCCESS)</span><br><span style="color: hsl(120, 100%, 40%);">+   {</span><br><span style="color: hsl(120, 100%, 40%);">+      st->initialised = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+   } else {</span><br><span style="color: hsl(120, 100%, 40%);">+      speex_resampler_destroy(st);</span><br><span style="color: hsl(120, 100%, 40%);">+      st = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span>    if (err)</span><br><span style="color: hsl(0, 100%, 40%);">-      *err = RESAMPLER_ERR_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+      *err = filter_err;</span><br><span> </span><br><span>    return st;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- void speex_resampler_destroy(SpeexResamplerState *st)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT void speex_resampler_destroy(SpeexResamplerState *st)</span><br><span> {</span><br><span>    speex_free(st->mem);</span><br><span>    speex_free(st->sinc_table);</span><br><span>@@ -829,9 +903,9 @@</span><br><span> }</span><br><span> </span><br><span> #ifdef FIXED_POINT</span><br><span style="color: hsl(0, 100%, 40%);">- 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)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT 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)</span><br><span> #else</span><br><span style="color: hsl(0, 100%, 40%);">- 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)</span><br><span style="color: hsl(120, 100%, 40%);">+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)</span><br><span> #endif</span><br><span> {</span><br><span>    int j;</span><br><span>@@ -866,13 +940,13 @@</span><br><span>    }</span><br><span>    *in_len -= ilen;</span><br><span>    *out_len -= olen;</span><br><span style="color: hsl(0, 100%, 40%);">-   return RESAMPLER_ERR_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+   return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;</span><br><span> }</span><br><span> </span><br><span> #ifdef FIXED_POINT</span><br><span style="color: hsl(0, 100%, 40%);">- 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)</span><br><span style="color: hsl(120, 100%, 40%);">+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)</span><br><span> #else</span><br><span style="color: hsl(0, 100%, 40%);">- 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)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT 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)</span><br><span> #endif</span><br><span> {</span><br><span>    int j;</span><br><span>@@ -940,20 +1014,22 @@</span><br><span>    *in_len -= ilen;</span><br><span>    *out_len -= olen;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return RESAMPLER_ERR_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+   return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)</span><br><span> {</span><br><span>    spx_uint32_t i;</span><br><span>    int istride_save, ostride_save;</span><br><span style="color: hsl(0, 100%, 40%);">-   spx_uint32_t bak_len = *out_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   spx_uint32_t bak_out_len = *out_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   spx_uint32_t bak_in_len = *in_len;</span><br><span>    istride_save = st->in_stride;</span><br><span>    ostride_save = st->out_stride;</span><br><span>    st->in_stride = st->out_stride = st->nb_channels;</span><br><span>    for (i=0;i<st->nb_channels;i++)</span><br><span>    {</span><br><span style="color: hsl(0, 100%, 40%);">-      *out_len = bak_len;</span><br><span style="color: hsl(120, 100%, 40%);">+      *out_len = bak_out_len;</span><br><span style="color: hsl(120, 100%, 40%);">+      *in_len = bak_in_len;</span><br><span>       if (in != NULL)</span><br><span>          speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);</span><br><span>       else</span><br><span>@@ -961,20 +1037,22 @@</span><br><span>    }</span><br><span>    st->in_stride = istride_save;</span><br><span>    st->out_stride = ostride_save;</span><br><span style="color: hsl(0, 100%, 40%);">-   return RESAMPLER_ERR_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+   return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- 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)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT 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)</span><br><span> {</span><br><span>    spx_uint32_t i;</span><br><span>    int istride_save, ostride_save;</span><br><span style="color: hsl(0, 100%, 40%);">-   spx_uint32_t bak_len = *out_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   spx_uint32_t bak_out_len = *out_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   spx_uint32_t bak_in_len = *in_len;</span><br><span>    istride_save = st->in_stride;</span><br><span>    ostride_save = st->out_stride;</span><br><span>    st->in_stride = st->out_stride = st->nb_channels;</span><br><span>    for (i=0;i<st->nb_channels;i++)</span><br><span>    {</span><br><span style="color: hsl(0, 100%, 40%);">-      *out_len = bak_len;</span><br><span style="color: hsl(120, 100%, 40%);">+      *out_len = bak_out_len;</span><br><span style="color: hsl(120, 100%, 40%);">+      *in_len = bak_in_len;</span><br><span>       if (in != NULL)</span><br><span>          speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);</span><br><span>       else</span><br><span>@@ -982,21 +1060,21 @@</span><br><span>    }</span><br><span>    st->in_stride = istride_save;</span><br><span>    st->out_stride = ostride_save;</span><br><span style="color: hsl(0, 100%, 40%);">-   return RESAMPLER_ERR_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+   return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)</span><br><span> {</span><br><span>    return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)</span><br><span> {</span><br><span>    *in_rate = st->in_rate;</span><br><span>    *out_rate = st->out_rate;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- 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)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT 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)</span><br><span> {</span><br><span>    spx_uint32_t fact;</span><br><span>    spx_uint32_t old_den;</span><br><span>@@ -1031,17 +1109,17 @@</span><br><span>    }</span><br><span> </span><br><span>    if (st->initialised)</span><br><span style="color: hsl(0, 100%, 40%);">-      update_filter(st);</span><br><span style="color: hsl(120, 100%, 40%);">+      return update_filter(st);</span><br><span>    return RESAMPLER_ERR_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)</span><br><span> {</span><br><span>    *ratio_num = st->num_rate;</span><br><span>    *ratio_den = st->den_rate;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- int speex_resampler_set_quality(SpeexResamplerState *st, int quality)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality)</span><br><span> {</span><br><span>    if (quality > 10 || quality < 0)</span><br><span>       return RESAMPLER_ERR_INVALID_ARG;</span><br><span>@@ -1049,46 +1127,46 @@</span><br><span>       return RESAMPLER_ERR_SUCCESS;</span><br><span>    st->quality = quality;</span><br><span>    if (st->initialised)</span><br><span style="color: hsl(0, 100%, 40%);">-      update_filter(st);</span><br><span style="color: hsl(120, 100%, 40%);">+      return update_filter(st);</span><br><span>    return RESAMPLER_ERR_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)</span><br><span> {</span><br><span>    *quality = st->quality;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)</span><br><span> {</span><br><span>    st->in_stride = stride;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)</span><br><span> {</span><br><span>    *stride = st->in_stride;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)</span><br><span> {</span><br><span>    st->out_stride = stride;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)</span><br><span> {</span><br><span>    *stride = st->out_stride;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- int speex_resampler_get_input_latency(SpeexResamplerState *st)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st)</span><br><span> {</span><br><span>   return st->filt_len / 2;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- int speex_resampler_get_output_latency(SpeexResamplerState *st)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st)</span><br><span> {</span><br><span>   return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- int speex_resampler_skip_zeros(SpeexResamplerState *st)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st)</span><br><span> {</span><br><span>    spx_uint32_t i;</span><br><span>    for (i=0;i<st->nb_channels;i++)</span><br><span>@@ -1096,15 +1174,21 @@</span><br><span>    return RESAMPLER_ERR_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- int speex_resampler_reset_mem(SpeexResamplerState *st)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st)</span><br><span> {</span><br><span>    spx_uint32_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i=0;i<st->nb_channels;i++)</span><br><span style="color: hsl(120, 100%, 40%);">+   {</span><br><span style="color: hsl(120, 100%, 40%);">+      st->last_sample[i] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      st->magic_samples[i] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      st->samp_frac_num[i] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span>    for (i=0;i<st->nb_channels*(st->filt_len-1);i++)</span><br><span>       st->mem[i] = 0;</span><br><span>    return RESAMPLER_ERR_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- const char *speex_resampler_strerror(int err)</span><br><span style="color: hsl(120, 100%, 40%);">+EXPORT const char *speex_resampler_strerror(int err)</span><br><span> {</span><br><span>    switch (err)</span><br><span>    {</span><br><span>diff --git a/codecs/speex/speex_resampler.h b/codecs/speex/speex_resampler.h</span><br><span>index d02022d..4d410d6 100644</span><br><span>--- a/codecs/speex/speex_resampler.h</span><br><span>+++ b/codecs/speex/speex_resampler.h</span><br><span>@@ -39,8 +39,6 @@</span><br><span> #ifndef SPEEX_RESAMPLER_H</span><br><span> #define SPEEX_RESAMPLER_H</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define OUTSIDE_SPEEX</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> #ifdef OUTSIDE_SPEEX</span><br><span> </span><br><span> /********* WARNING: MENTAL SANITY ENDS HERE *************/</span><br><span>@@ -48,7 +46,7 @@</span><br><span> /* If the resampler is defined outside of Speex, we change the symbol names so that</span><br><span>    there won't be any clash if linking with Speex later on. */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define RANDOM_PREFIX ast</span><br><span style="color: hsl(120, 100%, 40%);">+#define RANDOM_PREFIX speex</span><br><span> #ifndef RANDOM_PREFIX</span><br><span> #error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes"</span><br><span> #endif</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/12788">change 12788</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/12788"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 17 </div>
<div style="display:none"> Gerrit-Change-Id: Idd07bf341e89ac999c7f5701d9b72b8a9cb11e82 </div>
<div style="display:none"> Gerrit-Change-Number: 12788 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Sean Bright <sean.bright@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Sean Bright <sean.bright@gmail.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>