Rework output resampler handling to deal with case where fewer samples are consumed than available
This commit is contained in:
@@ -201,13 +201,6 @@ BQResampler::resampleInterleaved(float *const out,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < incount_samples) {
|
|
||||||
std::cerr << "only used " << i << " of " << incount_samples
|
|
||||||
<< " samples to generate output count " << o
|
|
||||||
<< " (outspace_samples was " << outspace_samples << ")"
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fbufsize = m_fade->buffer.size();
|
int fbufsize = m_fade->buffer.size();
|
||||||
int fi = 0, fo = 0;
|
int fi = 0, fo = 0;
|
||||||
while (fo < o && m_fade_count > 0) {
|
while (fo < o && m_fade_count > 0) {
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ R3LiveShifter::shift(const float *const *input, float *const *output)
|
|||||||
int requiredInOutbuf = 1 + int(ceil(incount / outRatio));
|
int requiredInOutbuf = 1 + int(ceil(incount / outRatio));
|
||||||
generate(requiredInOutbuf);
|
generate(requiredInOutbuf);
|
||||||
|
|
||||||
int got = readOut(output, incount, 0);
|
int got = readOut(output, incount);
|
||||||
|
|
||||||
if (got < incount) {
|
if (got < incount) {
|
||||||
m_log.log(0, "R3LiveShifter::shift: ERROR: internal error: insufficient data at output (wanted, got)", incount, got);
|
m_log.log(0, "R3LiveShifter::shift: ERROR: internal error: insufficient data at output (wanted, got)", incount, got);
|
||||||
@@ -597,7 +597,7 @@ R3LiveShifter::generate(int requiredInOutbuf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
R3LiveShifter::readOut(float *const *output, int outcount, int origin)
|
R3LiveShifter::readOut(float *const *output, int outcount)
|
||||||
{
|
{
|
||||||
double outRatio = 1.0;
|
double outRatio = 1.0;
|
||||||
|
|
||||||
@@ -613,13 +613,23 @@ R3LiveShifter::readOut(float *const *output, int outcount, int origin)
|
|||||||
|
|
||||||
m_log.log(2, "R3LiveShifter::readOut: outcount and ratio", outcount, outRatio);
|
m_log.log(2, "R3LiveShifter::readOut: outcount and ratio", outcount, outRatio);
|
||||||
|
|
||||||
int fromOutbuf = int(floor(outcount / outRatio));
|
int resampledCount = 0;
|
||||||
|
bool fillingTail = true;
|
||||||
|
|
||||||
m_log.log(2, "R3LiveShifter::readOut: origin and fromOutbuf", origin, fromOutbuf);
|
while (resampledCount < outcount) {
|
||||||
|
|
||||||
|
int fromOutbuf;
|
||||||
|
|
||||||
|
if (fillingTail) {
|
||||||
|
fromOutbuf = 1;
|
||||||
|
} else {
|
||||||
|
fromOutbuf = int(floor(outcount / outRatio));
|
||||||
if (fromOutbuf == 0) {
|
if (fromOutbuf == 0) {
|
||||||
fromOutbuf = 1;
|
fromOutbuf = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.log(2, "R3LiveShifter::readOut: fromOutbuf", fromOutbuf);
|
||||||
|
|
||||||
int got = fromOutbuf;
|
int got = fromOutbuf;
|
||||||
|
|
||||||
@@ -630,62 +640,59 @@ R3LiveShifter::readOut(float *const *output, int outcount, int origin)
|
|||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
m_log.log(0, "R3LiveShifter::readOut: WARNING: channel imbalance detected");
|
m_log.log(0, "R3LiveShifter::readOut: WARNING: channel imbalance detected");
|
||||||
}
|
}
|
||||||
got = std::min(got, std::max(gotHere, 0));
|
|
||||||
}
|
}
|
||||||
|
got = std::min(got, std::max(gotHere, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.log(2, "R3LiveShifter::readOut: requested and got from outbufs", fromOutbuf, got);
|
m_log.log(2, "R3LiveShifter::readOut: requested and got from outbufs", fromOutbuf, got);
|
||||||
m_log.log(2, "R3LiveShifter::readOut: leaving behind", m_channelData.at(0)->outbuf->getReadSpace());
|
m_log.log(2, "R3LiveShifter::readOut: leaving behind", m_channelData.at(0)->outbuf->getReadSpace());
|
||||||
|
|
||||||
int resampledCount = 0;
|
|
||||||
|
|
||||||
if (got > 0) {
|
|
||||||
|
|
||||||
for (int c = 0; c < m_parameters.channels; ++c) {
|
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||||
auto &cd = m_channelData.at(c);
|
auto &cd = m_channelData.at(c);
|
||||||
m_channelAssembly.resampled[c] = cd->resampled.data();
|
m_channelAssembly.resampled[c] = cd->resampled.data();
|
||||||
m_channelAssembly.mixdown[c] = output[c] + origin;
|
m_channelAssembly.mixdown[c] = output[c] + resampledCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
resampledCount = m_outResampler->resample
|
auto resampledHere = m_outResampler->resample
|
||||||
(m_channelAssembly.mixdown.data(),
|
(m_channelAssembly.mixdown.data(),
|
||||||
outcount,
|
outcount - resampledCount,
|
||||||
m_channelAssembly.resampled.data(),
|
m_channelAssembly.resampled.data(),
|
||||||
got,
|
got,
|
||||||
outRatio,
|
outRatio,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
|
m_log.log(2, "R3LiveShifter::readOut: resampledHere", resampledHere);
|
||||||
|
|
||||||
|
if (got == 0 && resampledHere == 0) {
|
||||||
|
m_log.log(2, "R3LiveShifter::readOut: made no progress, finishing");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
resampledCount += resampledHere;
|
||||||
|
|
||||||
|
fillingTail = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (useMidSide()) {
|
if (useMidSide()) {
|
||||||
for (int i = 0; i < resampledCount; ++i) {
|
for (int i = 0; i < resampledCount; ++i) {
|
||||||
float m = output[0][origin + i];
|
float m = output[0][i];
|
||||||
float s = output[1][origin + i];
|
float s = output[1][i];
|
||||||
float l = m + s;
|
float l = m + s;
|
||||||
float r = m - s;
|
float r = m - s;
|
||||||
output[0][origin + i] = l;
|
output[0][i] = l;
|
||||||
output[1][origin + i] = r;
|
output[1][i] = r;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.log(2, "R3LiveShifter::readOut: resampled to", resampledCount);
|
m_log.log(2, "R3LiveShifter::readOut: resampled to", resampledCount);
|
||||||
|
|
||||||
if (resampledCount < outcount &&
|
|
||||||
m_channelData.at(0)->outbuf->getReadSpace() > 0) {
|
|
||||||
int remaining = outcount - resampledCount;
|
|
||||||
m_log.log(2, "R3LiveShifter::readOut: recursing to try to get the remaining",
|
|
||||||
remaining);
|
|
||||||
resampledCount += readOut(output, remaining, origin + resampledCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resampledCount < outcount) {
|
if (resampledCount < outcount) {
|
||||||
if (m_firstProcess) {
|
if (m_firstProcess) {
|
||||||
m_log.log(2, "R3LiveShifter::readOut: resampler left us short on first process, pre-padding output: expected and obtained", outcount, resampledCount);
|
m_log.log(2, "R3LiveShifter::readOut: resampler left us short on first process, pre-padding output: expected and obtained", outcount, resampledCount);
|
||||||
int prepad = outcount - resampledCount;
|
int prepad = outcount - resampledCount;
|
||||||
for (int c = 0; c < m_parameters.channels; ++c) {
|
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||||
v_move(output[c] + origin + prepad,
|
v_move(output[c] + prepad, output[c], resampledCount);
|
||||||
output[c] + origin,
|
v_zero(output[c], prepad);
|
||||||
resampledCount);
|
|
||||||
v_zero(output[c] + origin, prepad);
|
|
||||||
}
|
}
|
||||||
resampledCount = outcount;
|
resampledCount = outcount;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ protected:
|
|||||||
|
|
||||||
void readIn(const float *const *input);
|
void readIn(const float *const *input);
|
||||||
void generate(int required);
|
void generate(int required);
|
||||||
int readOut(float *const *output, int outcount, int origin);
|
int readOut(float *const *output, int outcount);
|
||||||
|
|
||||||
void createResamplers();
|
void createResamplers();
|
||||||
void analyseChannel(int channel, int inhop, int prevInhop, int prevOuthop);
|
void analyseChannel(int channel, int inhop, int prevInhop, int prevOuthop);
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ static void check_sinusoid_unchanged(int n, int rate, float freq,
|
|||||||
|
|
||||||
RubberBandLiveShifter shifter(rate, 1, options);
|
RubberBandLiveShifter shifter(rate, 1, options);
|
||||||
|
|
||||||
shifter.setPitchScale(2.66968);
|
// shifter.setPitchScale(2.66968);
|
||||||
|
|
||||||
int blocksize = shifter.getBlockSize();
|
int blocksize = shifter.getBlockSize();
|
||||||
BOOST_TEST(blocksize == 512);
|
BOOST_TEST(blocksize == 512);
|
||||||
@@ -120,7 +120,7 @@ BOOST_AUTO_TEST_CASE(sinusoid_unchanged_mode_a)
|
|||||||
RubberBandLiveShifter::OptionPitchModeA;
|
RubberBandLiveShifter::OptionPitchModeA;
|
||||||
int n = 100000;
|
int n = 100000;
|
||||||
|
|
||||||
check_sinusoid_unchanged(n, 44100, 440.f, options, true);
|
check_sinusoid_unchanged(n, 44100, 440.f, options, false);
|
||||||
check_sinusoid_unchanged(n, 48000, 260.f, options, false);
|
check_sinusoid_unchanged(n, 48000, 260.f, options, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user