diff --git a/src/common/Resampler.cpp b/src/common/Resampler.cpp index df46471..d256820 100644 --- a/src/common/Resampler.cpp +++ b/src/common/Resampler.cpp @@ -26,6 +26,8 @@ #include "Allocators.h" #include "VectorOps.h" +#include "mathmisc.h" + #include #include @@ -1220,18 +1222,22 @@ D_Speex::setRatio(double ratio) // Speex wants a ratio of two unsigned integers, not a single // float. Let's do that. - unsigned int big = 272408136U; - unsigned int denom = 1, num = 1; - - if (ratio < 1.f) { - denom = big; - double dnum = double(big) * double(ratio); - num = (unsigned int)dnum; - } else if (ratio > 1.f) { - num = big; - double ddenom = double(big) / double(ratio); - denom = (unsigned int)ddenom; + int max_denom = 96000; + if (ratio > 1.0) { + max_denom = int(ceil(96000 / ratio)); } + + int inum, idenom; + pickNearestRational(ratio, max_denom, inum, idenom); + + if (inum < 0 || idenom < 0) { + cerr << "Resampler::setRatio: Internal error: " + << "numerator or denominator < 0 (" + << inum << "/" << idenom << ")" << endl; + return; + } + + unsigned int num = inum, denom = idenom; if (m_debugLevel > 1) { cerr << "D_Speex: Desired ratio " << ratio << ", requesting ratio " @@ -1246,8 +1252,12 @@ D_Speex::setRatio(double ratio) (m_resampler, denom, num, fromRate, toRate); if (err) { - cerr << "Resampler::Resampler: failed to set rate on Speex resampler" - << endl; + cerr << "Resampler::Resampler: failed to set rate on Speex resampler" + << " (with ratio = " << ratio << " [ratio-1 = " << ratio - 1.0 + << "], denom = " << denom + << ", num = " << num << ", fromRate = " << fromRate + << ", toRate = " << toRate << ", err = " << err + << ")" << endl; #ifndef NO_EXCEPTIONS throw Resampler::ImplementationError; #endif