Bug#799176: #799176 - libspeexdsp1: Severe clipping of audio when libspeex resampler is used by ALSA or pulse audio
Erik Montnemery
erik at montnemery.com
Wed Sep 16 17:28:30 UTC 2015
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.
As a side note, why is the fixed point implementation compiled for armhf?
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.
Please note the changes only affect the fixed point implementation.
The remaining upstream changes to libsspeex/resampler.c seem to be:
- General cleanup, such as declaring constant as const
- Better error handling when allocating memory
- 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
Patch:
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
--- rc1.2_debian_changes/speex-1.2~rc1.2/libspeex/arch.h 2014-08-26
12:35:22.000000000 +0200
+++ backport_rc3_minimal/speex-1.2~rc1.2/libspeex/arch.h 2015-09-16
18:45:42.226989704 +0200
@@ -171,6 +171,7 @@ typedef float spx_word32_t;
#define VSHR32(a,shift) (a)
#define SATURATE16(x,a) (x)
#define SATURATE32(x,a) (x)
+#define SATURATE32PSHR(x,shift,a) (x)
#define PSHR(a,shift) (a)
#define SHR(a,shift) (a)
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
--- rc1.2_debian_changes/speex-1.2~rc1.2/libspeex/fixed_generic.h 2014-08-26
12:35:22.000000000 +0200
+++ backport_rc3_minimal/speex-1.2~rc1.2/libspeex/fixed_generic.h 2015-09-16
18:45:40.670989642 +0200
@@ -52,6 +52,10 @@
#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
+#define SATURATE32PSHR(x,shift,a) (((x)>=(SHL32(a,shift))) ? (a) : \
+ (x)<=-(SHL32(a,shift)) ? -(a) : \
+ (PSHR32(x, shift)))
+
#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))
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
--- rc1.2_debian_changes/speex-1.2~rc1.2/libspeex/resample.c 2015-09-15
20:21:30.000000000 +0200
+++ backport_rc3_minimal/speex-1.2~rc1.2/libspeex/resample.c 2015-09-16
18:45:43.878989770 +0200
@@ -337,7 +337,6 @@ static int resampler_basic_direct_single
const int frac_advance = st->frac_advance;
const spx_uint32_t den_rate = st->den_rate;
spx_word32_t sum;
- int j;
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >=
(spx_int32_t)*out_len))
{
@@ -345,20 +344,28 @@ static int resampler_basic_direct_single
const spx_word16_t *iptr = & in[last_sample];
#ifndef OVERRIDE_INNER_PRODUCT_SINGLE
- float accum[4] = {0,0,0,0};
-
+ int j;
+ sum = 0;
+ for(j=0;j<N;j++) sum += MULT16_16(sinc[j], iptr[j]);
+
+/* This code is slower on most DSPs which have only 2 accumulators.
+ Plus this this forces truncation to 32 bits and you lose the HW
guard bits.
+ I think we can trust the compiler and let it vectorize and/or unroll
itself.
+ spx_word32_t accum[4] = {0,0,0,0};
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];
+ accum[0] += MULT16_16(sinct[j], iptr[j]);
+ accum[1] += MULT16_16(sinct[j+1], iptr[j+1]);
+ accum[2] += MULT16_16(sinct[j+2], iptr[j+2]);
+ accum[3] += MULT16_16(sinct[j+3], iptr[j+3]);
}
sum = accum[0] + accum[1] + accum[2] + accum[3];
+*/
+ sum = SATURATE32PSHR(sum, 15, 32767);
#else
sum = inner_product_single(sinc, iptr, N);
#endif
- out[out_stride * out_sample++] = PSHR32(sum, 15);
+ out[out_stride * out_sample++] = sum;
last_sample += int_advance;
samp_frac_num += frac_advance;
if (samp_frac_num >= den_rate)
@@ -435,7 +442,6 @@ static int resampler_basic_interpolate_s
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;
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >=
(spx_int32_t)*out_len))
@@ -452,6 +458,7 @@ static int resampler_basic_interpolate_s
#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
+ int j;
spx_word32_t accum[4] = {0,0,0,0};
for(j=0;j<N;j++) {
@@ -463,13 +470,14 @@ static int resampler_basic_interpolate_s
}
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]);
+ 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));
+ sum = SATURATE32PSHR(sum, 15, 32767);
#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);
+ out[out_stride * out_sample++] = sum;
last_sample += int_advance;
samp_frac_num += frac_advance;
if (samp_frac_num >= den_rate)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.alioth.debian.org/pipermail/pkg-voip-maintainers/attachments/20150916/ab6da774/attachment-0001.html>
More information about the Pkg-voip-maintainers
mailing list