[Speex-dev] Bug in libspeexdsp resampler

John Ridges jridges at masque.com
Wed Aug 5 15:15:11 PDT 2009


There is a bug in "speex_resampler_process_interleaved_int" and 
"speex_resampler_process_interleaved_float" in the resampler. It seems 
that when "speex_resampler_process_int" is called for the first channel, 
"in_len" is set to the actual number of samples used (when output 
limited), which you would think would be OK to use for all the 
subsequent calls to "speex_resampler_process_int" for the other 
channels. However, there is some subtle difference (in the way 
fractional samples are computed, I suspect) that causes 
"speex_resampler_process_int" to sometimes return a value of "out_len" 
that is off by one when the changed "in_len" value is used, and even 
though "out_len" is reset before each channel, since it is the last 
channel that sets "out_len"s return value for 
"speex_resampler_process_interleaved_int", the wrong value is sometimes 
returned by that function (same goes for the float version).

My naive fix is to save the original "in_len" value and reset it before 
each call to "speex_resampler_process_int". There might be some more 
clever way to fix it deeper in the code, but this seems to work. The 
changed functions follow.

John Ridges



EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState 
*st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t 
*out_len)
{
spx_uint32_t i;
int istride_save, ostride_save;
spx_uint32_t bak_in_len = *in_len;
spx_uint32_t bak_out_len = *out_len;
istride_save = st->in_stride;
ostride_save = st->out_stride;
st->in_stride = st->out_stride = st->nb_channels;
for (i=0;i<st->nb_channels;i++)
{
*in_len = bak_in_len;
*out_len = bak_out_len;
if (in != NULL)
speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
else
speex_resampler_process_float(st, i, NULL, in_len, out+i, out_len);
}
st->in_stride = istride_save;
st->out_stride = ostride_save;
return RESAMPLER_ERR_SUCCESS;
}

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)
{
spx_uint32_t i;
int istride_save, ostride_save;
spx_uint32_t bak_in_len = *in_len;
spx_uint32_t bak_out_len = *out_len;
istride_save = st->in_stride;
ostride_save = st->out_stride;
st->in_stride = st->out_stride = st->nb_channels;
for (i=0;i<st->nb_channels;i++)
{
*in_len = bak_in_len;
*out_len = bak_out_len;
if (in != NULL)
speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
else
speex_resampler_process_int(st, i, NULL, in_len, out+i, out_len);
}
st->in_stride = istride_save;
st->out_stride = ostride_save;
return RESAMPLER_ERR_SUCCESS;
}




More information about the Speex-dev mailing list