Fix handling of final block in speex resampler - there is no guarantee a single pad call will return enough data on its own either

This commit is contained in:
Chris Cannam
2023-01-17 12:34:50 +00:00
parent cc3e265b26
commit b317d0e81a

View File

@@ -1174,26 +1174,37 @@ D_Speex::doResample(const float *data_in, unsigned int &uincount,
if (final) { if (final) {
int actual = int(uoutcount); int actual = int(uoutcount);
int expected = std::min(initial_outcount, int(round(uincount * ratio))); int expected = std::min(initial_outcount, int(round(uincount * ratio)));
if (actual < expected) { float *pad = nullptr;
while (actual < expected) {
unsigned int final_out = expected - actual; unsigned int final_out = expected - actual;
unsigned int final_in = (unsigned int)(round(final_out / ratio)); unsigned int final_in = (unsigned int)(round(final_out / ratio));
if (final_in > 0) { if (final_in == 0) {
float *pad = allocate_and_zero<float>(final_in * m_channels); break;
} else {
if (!pad) {
pad = allocate_and_zero<float>(final_in * m_channels);
}
err = speex_resampler_process_interleaved_float err = speex_resampler_process_interleaved_float
(m_resampler, (m_resampler,
pad, &final_in, pad, &final_in,
data_out + actual * m_channels, &final_out); data_out + actual * m_channels, &final_out);
deallocate(pad); actual += final_out;
uoutcount += final_out; uoutcount += final_out;
if (err) { if (err) {
cerr << "Resampler::Resampler: Speex resampler returned error " cerr << "Resampler::Resampler: Speex resampler returned error "
<< err << endl; << err << endl;
if (pad) {
deallocate(pad);
}
#ifndef NO_EXCEPTIONS #ifndef NO_EXCEPTIONS
throw Resampler::ImplementationError; throw Resampler::ImplementationError;
#endif #endif
} }
} }
} }
if (pad) {
deallocate(pad);
}
} }
} }