Experiment with small crossfade on resampler rate change

This commit is contained in:
Chris Cannam
2020-09-15 13:46:18 +01:00
parent 334f1b891d
commit de618103f7

View File

@@ -609,6 +609,10 @@ D_SRC::resample(const float *const R__ *const R__ in,
{ {
SRC_DATA data; SRC_DATA data;
static size_t n_in = 0, n_out = 0;
std::cerr << "Resampler::process: at input sample " << n_in << ", output sample " << n_out << ", incount = " << incount << ", ratio = " << ratio << ", incount * ratio = " << incount * ratio << std::endl;
int outcount = lrintf(ceilf(incount * ratio)); int outcount = lrintf(ceilf(incount * ratio));
if (m_channels == 1) { if (m_channels == 1) {
@@ -628,12 +632,57 @@ D_SRC::resample(const float *const R__ *const R__ in,
data.data_out = m_iout; data.data_out = m_iout;
} }
data.input_frames = incount;
data.output_frames = outcount;
data.src_ratio = ratio; data.src_ratio = ratio;
data.end_of_input = (final ? 1 : 0);
int err = src_process(m_src, &data); #ifdef PERFORM_LIBSAMPLERATE_XFADE
const int xfade = 10;
int err = 0;
if (ratio != m_lastRatio && outcount > xfade) {
int xin = lrintf(ceilf(xfade / ratio));
SRC_STATE *xsrc = src_clone(m_src, &err);
float *xbuf = 0;
if (err) {
std::cerr << "Resampler::process: libsamplerate error: "
<< src_strerror(err) << ", skipping xfade" << std::endl;
} else {
data.input_frames = xin;
data.output_frames = xfade;
data.end_of_input = false;
err = src_process(xsrc, &data);
xbuf = allocate<float>(xfade * m_channels);
v_copy(xbuf, data.data_out, xfade * m_channels);
src_delete(xsrc);
}
data.input_frames = incount;
data.output_frames = outcount;
data.end_of_input = (final ? 1 : 0);
src_set_ratio(m_src, ratio);
err = src_process(m_src, &data);
if (xbuf) {
for (int i = 0; i < xfade; ++i) {
for (int c = 0; c < m_channels; ++c) {
float g = float(i+1) / float(xfade);
float f = data.data_out[i * m_channels + c] * g +
xbuf[i * m_channels + c] * (1.f - g);
data.data_out[i * m_channels + c] = f;
}
}
deallocate<float>(xbuf);
}
} else {
#endif
data.input_frames = incount;
data.output_frames = outcount;
data.end_of_input = (final ? 1 : 0);
err = src_process(m_src, &data);
#ifdef PERFORM_LIBSAMPLERATE_XFADE
}
#endif
if (err) { if (err) {
std::cerr << "Resampler::process: libsamplerate error: " std::cerr << "Resampler::process: libsamplerate error: "
@@ -649,6 +698,13 @@ D_SRC::resample(const float *const R__ *const R__ in,
m_lastRatio = ratio; m_lastRatio = ratio;
n_in += incount;
n_out += data.output_frames_gen;
std::cerr << "outcount = " << data.output_frames_gen << std::endl;
// out[0][0] = 1.0;
return data.output_frames_gen; return data.output_frames_gen;
} }
@@ -942,6 +998,8 @@ D_Speex::D_Speex(Resampler::Quality quality, int channels, int maxBufferSize,
<< std::endl; << std::endl;
} }
q = 10; //!!!
int err = 0; int err = 0;
m_resampler = speex_resampler_init_frac(m_channels, m_resampler = speex_resampler_init_frac(m_channels,
1, 1, 1, 1,
@@ -1030,7 +1088,10 @@ D_Speex::resample(const float *const R__ *const R__ in,
} }
unsigned int uincount = incount; unsigned int uincount = incount;
unsigned int outcount = lrintf(ceilf(incount * ratio)); //!!! inexact now
// This doesn't have to be exact, but it does have to be
// sufficient, hence going over by one
unsigned int outcount = lrintf(ceilf((incount + 1) * ratio));
float *data_in, *data_out; float *data_in, *data_out;
@@ -1057,16 +1118,16 @@ D_Speex::resample(const float *const R__ *const R__ in,
data_out, data_out,
&outcount); &outcount);
// if (incount != int(uincount)) { if (incount != int(uincount)) {
// std::cerr << "Resampler: NOTE: Consumed " << uincount std::cerr << "Resampler: NOTE: Consumed " << uincount
// << " of " << incount << " frames" << std::endl; << " of " << incount << " frames" << std::endl;
// } }
// if (outcount != lrintf(ceilf(incount * ratio))) { if (outcount != lrintf(ceilf(incount * ratio))) {
// std::cerr << "Resampler: NOTE: Obtained " << outcount std::cerr << "Resampler: NOTE: Obtained " << outcount
// << " of " << lrintf(ceilf(incount * ratio)) << " frames" << " of " << lrintf(ceilf(incount * ratio)) << " frames"
// << std::endl; << std::endl;
// } }
//!!! check err, respond appropriately //!!! check err, respond appropriately