Ensure output accumulator is properly drained at finish. We rely on the calculated output count (in offline mode) to truncate properly.

This commit is contained in:
Chris Cannam
2022-07-07 10:35:01 +01:00
parent a66d2a5140
commit 263e0cbf70
3 changed files with 39 additions and 21 deletions

View File

@@ -988,7 +988,7 @@ int main(int argc, char **argv)
cerr << "in: " << countIn << ", out: " << countOut cerr << "in: " << countIn << ", out: " << countOut
<< ", ratio: " << float(countOut)/float(countIn) << ", ratio: " << float(countOut)/float(countIn)
<< ", ideal output: " << lrint(countIn * ratio) << ", ideal output: " << lrint(countIn * ratio)
<< ", error: " << abs(lrint(countIn * ratio) - int(countOut)) << ", error: " << int(countOut) - lrint(countIn * ratio)
<< endl; << endl;
#ifdef _WIN32 #ifdef _WIN32

View File

@@ -635,6 +635,11 @@ R3Stretcher::consume()
longest, longest,
longest, longest,
true); true);
if (outhop < 1) {
m_log.log(0, "R3Stretcher::consume: WARNING: outhop calculated as", outhop);
outhop = 1;
}
// Now inhop is the distance by which the input stream will be // Now inhop is the distance by which the input stream will be
// advanced after our current frame has been read, and outhop is // advanced after our current frame has been read, and outhop is
@@ -655,8 +660,10 @@ R3Stretcher::consume()
if (outhop != m_prevOuthop) { if (outhop != m_prevOuthop) {
m_log.log(2, "change in outhop", double(m_prevOuthop), double(outhop)); m_log.log(2, "change in outhop", double(m_prevOuthop), double(outhop));
} }
auto &cd0 = m_channelData.at(0);
while (m_channelData.at(0)->outbuf->getWriteSpace() >= outhop) { while (cd0->outbuf->getWriteSpace() >= outhop) {
// NB our ChannelData, ScaleData, and ChannelScaleData maps // NB our ChannelData, ScaleData, and ChannelScaleData maps
// contain shared_ptrs; whenever we retain one of them in a // contain shared_ptrs; whenever we retain one of them in a
@@ -664,13 +671,19 @@ R3Stretcher::consume()
// shared_ptr (as that is not realtime safe). Same goes for // shared_ptr (as that is not realtime safe). Same goes for
// the map iterators // the map iterators
int readSpace = m_channelData.at(0)->inbuf->getReadSpace(); int readSpace = cd0->inbuf->getReadSpace();
if (readSpace < longest) { if (readSpace < longest) {
if (m_mode == ProcessMode::Finished) { if (m_mode == ProcessMode::Finished) {
if (readSpace == 0) { if (readSpace == 0) {
break; int fill = cd0->scales.at(longest)->accumulatorFill;
if (fill == 0) {
break;
} else {
m_log.log(1, "finished reading input, but samples remaining in output accumulator", fill);
}
} }
} else { } else {
// await more input
break; break;
} }
} }
@@ -712,17 +725,7 @@ R3Stretcher::consume()
// Resynthesis // Resynthesis
for (int c = 0; c < channels; ++c) { for (int c = 0; c < channels; ++c) {
synthesiseChannel(c, outhop); synthesiseChannel(c, outhop, readSpace == 0);
}
// We now have outhop samples at the start of the mixdown
// buffer, but they aren't necessarily all valid, because we
// might have had fewer than outhop at the start of inbuf
// (when finished and draining)
int validCount = outhop;
if (readSpace < outhop) {
validCount = readSpace;
} }
// Resample // Resample
@@ -747,14 +750,14 @@ R3Stretcher::consume()
(m_channelAssembly.resampled.data(), (m_channelAssembly.resampled.data(),
m_channelData[0]->resampled.size(), m_channelData[0]->resampled.size(),
m_channelAssembly.mixdown.data(), m_channelAssembly.mixdown.data(),
validCount, outhop,
1.0 / m_pitchScale, 1.0 / m_pitchScale,
m_mode == ProcessMode::Finished && readSpace < inhop); m_mode == ProcessMode::Finished && readSpace < inhop);
} }
// Emit // Emit
int writeCount = validCount; int writeCount = outhop;
if (resampling) { if (resampling) {
writeCount = resampledCount; writeCount = resampledCount;
} }
@@ -792,7 +795,7 @@ R3Stretcher::consume()
m_totalOutputDuration += writeCount; m_totalOutputDuration += writeCount;
if (m_startSkip > 0) { if (m_startSkip > 0) {
int rs = m_channelData.at(0)->outbuf->getReadSpace(); int rs = cd0->outbuf->getReadSpace();
int toSkip = std::min(m_startSkip, rs); int toSkip = std::min(m_startSkip, rs);
for (int c = 0; c < channels; ++c) { for (int c = 0; c < channels; ++c) {
m_channelData.at(c)->outbuf->skip(toSkip); m_channelData.at(c)->outbuf->skip(toSkip);
@@ -1146,7 +1149,7 @@ R3Stretcher::adjustPreKick(int c)
} }
void void
R3Stretcher::synthesiseChannel(int c, int outhop) R3Stretcher::synthesiseChannel(int c, int outhop, bool draining)
{ {
int longest = m_guideConfiguration.longestFftSize; int longest = m_guideConfiguration.longestFftSize;
@@ -1229,6 +1232,18 @@ R3Stretcher::synthesiseChannel(int c, int outhop)
int n = scale->accumulator.size() - outhop; int n = scale->accumulator.size() - outhop;
v_move(accptr, accptr + outhop, n); v_move(accptr, accptr + outhop, n);
v_zero(accptr + n, outhop); v_zero(accptr + n, outhop);
if (draining) {
if (scale->accumulatorFill > outhop) {
auto newFill = scale->accumulatorFill - outhop;
m_log.log(2, "draining: reducing accumulatorFill from, to", scale->accumulatorFill, newFill);
scale->accumulatorFill = newFill;
} else {
scale->accumulatorFill = 0;
}
} else {
scale->accumulatorFill = scale->accumulator.size();
}
} }
} }

View File

@@ -129,6 +129,7 @@ protected:
FixedVector<process_t> prevMag; FixedVector<process_t> prevMag;
FixedVector<process_t> pendingKick; FixedVector<process_t> pendingKick;
FixedVector<process_t> accumulator; FixedVector<process_t> accumulator;
int accumulatorFill;
ChannelScaleData(int _fftSize, int _longestFftSize) : ChannelScaleData(int _fftSize, int _longestFftSize) :
fftSize(_fftSize), fftSize(_fftSize),
@@ -141,12 +142,14 @@ protected:
advancedPhase(bufSize, 0.f), advancedPhase(bufSize, 0.f),
prevMag(bufSize, 0.f), prevMag(bufSize, 0.f),
pendingKick(bufSize, 0.f), pendingKick(bufSize, 0.f),
accumulator(_longestFftSize, 0.f) accumulator(_longestFftSize, 0.f),
accumulatorFill(0)
{ } { }
void reset() { void reset() {
v_zero(prevMag.data(), prevMag.size()); v_zero(prevMag.data(), prevMag.size());
v_zero(accumulator.data(), accumulator.size()); v_zero(accumulator.data(), accumulator.size());
accumulatorFill = 0;
} }
private: private:
@@ -322,7 +325,7 @@ protected:
void analyseFormant(int channel); void analyseFormant(int channel);
void adjustFormant(int channel); void adjustFormant(int channel);
void adjustPreKick(int channel); void adjustPreKick(int channel);
void synthesiseChannel(int channel, int outhop); void synthesiseChannel(int channel, int outhop, bool draining);
struct ToPolarSpec { struct ToPolarSpec {
int magFromBin; int magFromBin;