[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