<div dir="ltr">The information in the bug report was a bit lacking, I should have mentioned that the fixed point implementation of the resampler is used on armhf architecture where I see the issue.<div>As a side note, why is the fixed point implementation compiled for armhf?</div><div><br></div><div>A patch with the necessary changes to libspeex/resampler.c from upstream to solve the issue can be found at the end of this message.</div><div>Please note the changes only affect the fixed point implementation.</div><div><br></div><div>The remaining upstream changes to libsspeex/resampler.c seem to be:</div><div> - General cleanup, such as declaring constant as const</div><div> - Better error handling when allocating memory</div><div> - There are some changes in update_filter, but it is not obvious to me if it is also related to the error handling or actual bug fixes</div><div><br></div><div>Patch:</div><div><div>diff -rup rc1.2_debian_changes/speex-1.2~rc1.2/libspeex/arch.h backport_rc3_minimal/speex-1.2~rc1.2/libspeex/arch.h</div><div>--- rc1.2_debian_changes/speex-1.2~rc1.2/libspeex/arch.h<span class="" style="white-space:pre">     </span>2014-08-26 12:35:22.000000000 +0200</div><div>+++ backport_rc3_minimal/speex-1.2~rc1.2/libspeex/arch.h<span class="" style="white-space:pre">        </span>2015-09-16 18:45:42.226989704 +0200</div><div>@@ -171,6 +171,7 @@ typedef float spx_word32_t;</div><div> #define VSHR32(a,shift) (a)</div><div> #define SATURATE16(x,a) (x)</div><div> #define SATURATE32(x,a) (x)</div><div>+#define SATURATE32PSHR(x,shift,a) (x)</div><div> </div><div> #define PSHR(a,shift)       (a)</div><div> #define SHR(a,shift)       (a)</div><div>diff -rup rc1.2_debian_changes/speex-1.2~rc1.2/libspeex/fixed_generic.h backport_rc3_minimal/speex-1.2~rc1.2/libspeex/fixed_generic.h</div><div>--- rc1.2_debian_changes/speex-1.2~rc1.2/libspeex/fixed_generic.h<span class="" style="white-space:pre">      </span>2014-08-26 12:35:22.000000000 +0200</div><div>+++ backport_rc3_minimal/speex-1.2~rc1.2/libspeex/fixed_generic.h<span class="" style="white-space:pre">       </span>2015-09-16 18:45:40.670989642 +0200</div><div>@@ -52,6 +52,10 @@</div><div> #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))</div><div> #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))</div><div> </div><div>+#define SATURATE32PSHR(x,shift,a) (((x)>=(SHL32(a,shift))) ? (a) : \</div><div>+                                   (x)<=-(SHL32(a,shift)) ? -(a) : \</div><div>+                                   (PSHR32(x, shift)))</div><div>+</div><div> #define SHR(a,shift) ((a) >> (shift))</div><div> #define SHL(a,shift) ((spx_word32_t)(a) << (shift))</div><div> #define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))</div><div>diff -rup rc1.2_debian_changes/speex-1.2~rc1.2/libspeex/resample.c backport_rc3_minimal/speex-1.2~rc1.2/libspeex/resample.c</div><div>--- rc1.2_debian_changes/speex-1.2~rc1.2/libspeex/resample.c<span class="" style="white-space:pre">   </span>2015-09-15 20:21:30.000000000 +0200</div><div>+++ backport_rc3_minimal/speex-1.2~rc1.2/libspeex/resample.c<span class="" style="white-space:pre">    </span>2015-09-16 18:45:43.878989770 +0200</div><div>@@ -337,7 +337,6 @@ static int resampler_basic_direct_single</div><div>    const int frac_advance = st->frac_advance;</div><div>    const spx_uint32_t den_rate = st->den_rate;</div><div>    spx_word32_t sum;</div><div>-   int j;</div><div> </div><div>    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))</div><div>    {</div><div>@@ -345,20 +344,28 @@ static int resampler_basic_direct_single</div><div>       const spx_word16_t *iptr = & in[last_sample];</div><div> </div><div> #ifndef OVERRIDE_INNER_PRODUCT_SINGLE</div><div>-      float accum[4] = {0,0,0,0};</div><div>-</div><div>+      int j;</div><div>+      sum = 0;</div><div>+      for(j=0;j<N;j++) sum += MULT16_16(sinc[j], iptr[j]);</div><div>+</div><div>+/*    This code is slower on most DSPs which have only 2 accumulators.</div><div>+      Plus this this forces truncation to 32 bits and you lose the HW guard bits.</div><div>+      I think we can trust the compiler and let it vectorize and/or unroll itself.</div><div>+      spx_word32_t accum[4] = {0,0,0,0};</div><div>       for(j=0;j<N;j+=4) {</div><div>-        accum[0] += sinc[j]*iptr[j];</div><div>-        accum[1] += sinc[j+1]*iptr[j+1];</div><div>-        accum[2] += sinc[j+2]*iptr[j+2];</div><div>-        accum[3] += sinc[j+3]*iptr[j+3];</div><div>+        accum[0] += MULT16_16(sinct[j], iptr[j]);</div><div>+        accum[1] += MULT16_16(sinct[j+1], iptr[j+1]);</div><div>+        accum[2] += MULT16_16(sinct[j+2], iptr[j+2]);</div><div>+        accum[3] += MULT16_16(sinct[j+3], iptr[j+3]);</div><div>       }</div><div>       sum = accum[0] + accum[1] + accum[2] + accum[3];</div><div>+*/</div><div>+      sum = SATURATE32PSHR(sum, 15, 32767);</div><div> #else</div><div>       sum = inner_product_single(sinc, iptr, N);</div><div> #endif</div><div> </div><div>-      out[out_stride * out_sample++] = PSHR32(sum, 15);</div><div>+      out[out_stride * out_sample++] = sum;</div><div>       last_sample += int_advance;</div><div>       samp_frac_num += frac_advance;</div><div>       if (samp_frac_num >= den_rate)</div><div>@@ -435,7 +442,6 @@ static int resampler_basic_interpolate_s</div><div>    const int int_advance = st->int_advance;</div><div>    const int frac_advance = st->frac_advance;</div><div>    const spx_uint32_t den_rate = st->den_rate;</div><div>-   int j;</div><div>    spx_word32_t sum;</div><div> </div><div>    while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))</div><div>@@ -452,6 +458,7 @@ static int resampler_basic_interpolate_s</div><div> </div><div> </div><div> #ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE</div><div>+      int j;</div><div>       spx_word32_t accum[4] = {0,0,0,0};</div><div> </div><div>       for(j=0;j<N;j++) {</div><div>@@ -463,13 +470,14 @@ static int resampler_basic_interpolate_s</div><div>       }</div><div> </div><div>       cubic_coef(frac, interp);</div><div>-      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]);</div><div>+      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));</div><div>+      sum = SATURATE32PSHR(sum, 15, 32767);</div><div> #else</div><div>       cubic_coef(frac, interp);</div><div>       sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);</div><div> #endif</div><div>       </div><div>-      out[out_stride * out_sample++] = PSHR32(sum,15);</div><div>+      out[out_stride * out_sample++] = sum;</div><div>       last_sample += int_advance;</div><div>       samp_frac_num += frac_advance;</div><div>       if (samp_frac_num >= den_rate)</div></div><div><br></div></div>