diff options
author | Wim Taymans <wtaymans@redhat.com> | 2016-02-04 12:49:49 +0300 |
---|---|---|
committer | Tristan Matthews <tmatth@videolan.org> | 2016-03-06 20:33:51 +0300 |
commit | d5fade684a4f0ea1419901173d8a254742a6f3a9 (patch) | |
tree | 04cfb57185a8e19a9df4fab22cfbe9c9cd4ecfcf | |
parent | d08a14462744654f7097f17943d8e2ddc0dfe93e (diff) |
resample: avoid overflow in phase calculation
Make sure we don't overflow when calculating the phase for the new
sample rate.
Signed-off-by: Tristan Matthews <tmatth@videolan.org>
-rw-r--r-- | libspeexdsp/resample.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/libspeexdsp/resample.c b/libspeexdsp/resample.c index e69b309..373d713 100644 --- a/libspeexdsp/resample.c +++ b/libspeexdsp/resample.c @@ -1080,6 +1080,36 @@ static inline spx_uint32_t _gcd(spx_uint32_t a, spx_uint32_t b) return a; } +static spx_uint32_t _muldiv(spx_uint32_t a, spx_uint32_t b, spx_uint32_t c) +{ + spx_uint32_t q = 0, r = 0; + spx_uint32_t qn = b / c; + spx_uint32_t rn = b % c; + + while(a) + { + if (a & 1) + { + q += qn; + r += rn; + if (r >= c) + { + q++; + r -= c; + } + } + a >>= 1; + qn <<= 1; + rn <<= 1; + if (rn >= c) + { + qn++; + rn -= c; + } + } + return q; +} + 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) { spx_uint32_t fact; @@ -1103,7 +1133,7 @@ EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t r { for (i=0;i<st->nb_channels;i++) { - st->samp_frac_num[i]=st->samp_frac_num[i]*st->den_rate/old_den; + st->samp_frac_num[i]= _muldiv(st->samp_frac_num[i],st->den_rate,old_den); /* Safety net */ if (st->samp_frac_num[i] >= st->den_rate) st->samp_frac_num[i] = st->den_rate-1; |