Work on proper sizing of internal buffers
This commit is contained in:
@@ -105,16 +105,19 @@ R3Stretcher::initialise()
|
|||||||
int inRingBufferSize = getWindowSourceSize() * 16;
|
int inRingBufferSize = getWindowSourceSize() * 16;
|
||||||
int outRingBufferSize = getWindowSourceSize() * 16;
|
int outRingBufferSize = getWindowSourceSize() * 16;
|
||||||
|
|
||||||
|
int hopBufferSize =
|
||||||
|
2 * std::max(m_limits.maxInhop, m_limits.maxPreferredOuthop);
|
||||||
|
|
||||||
m_channelData.clear();
|
m_channelData.clear();
|
||||||
|
|
||||||
for (int c = 0; c < m_parameters.channels; ++c) {
|
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||||
m_channelData.push_back(std::make_shared<ChannelData>
|
m_channelData.push_back(std::make_shared<ChannelData>
|
||||||
(segmenterParameters,
|
(segmenterParameters,
|
||||||
classifierParameters,
|
classifierParameters,
|
||||||
m_guideConfiguration.longestFftSize,
|
|
||||||
getWindowSourceSize(),
|
getWindowSourceSize(),
|
||||||
inRingBufferSize,
|
inRingBufferSize,
|
||||||
outRingBufferSize));
|
outRingBufferSize,
|
||||||
|
hopBufferSize));
|
||||||
for (int b = 0; b < m_guideConfiguration.fftBandLimitCount; ++b) {
|
for (int b = 0; b < m_guideConfiguration.fftBandLimitCount; ++b) {
|
||||||
const auto &band = m_guideConfiguration.fftBandLimits[b];
|
const auto &band = m_guideConfiguration.fftBandLimits[b];
|
||||||
int fftSize = band.fftSize;
|
int fftSize = band.fftSize;
|
||||||
@@ -636,17 +639,30 @@ R3Stretcher::getSamplesRequired() const
|
|||||||
void
|
void
|
||||||
R3Stretcher::setMaxProcessSize(size_t n)
|
R3Stretcher::setMaxProcessSize(size_t n)
|
||||||
{
|
{
|
||||||
size_t oldSize = m_channelData[0]->inbuf->getSize();
|
size_t oldInSize = m_channelData[0]->inbuf->getSize();
|
||||||
size_t newSize = getWindowSourceSize() + n;
|
size_t newInSize = getWindowSourceSize() + n;
|
||||||
|
|
||||||
if (newSize > oldSize) {
|
size_t oldOutSize = m_channelData[0]->outbuf->getSize();
|
||||||
m_log.log(1, "setMaxProcessSize: resizing from and to", oldSize, newSize);
|
size_t newOutSize = newInSize;
|
||||||
|
|
||||||
|
if (newInSize > oldInSize) {
|
||||||
|
m_log.log(1, "setMaxProcessSize: resizing inbuf from and to", oldInSize, newInSize);
|
||||||
for (int c = 0; c < m_parameters.channels; ++c) {
|
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||||
m_channelData[c]->inbuf = std::unique_ptr<RingBuffer<float>>
|
m_channelData[c]->inbuf = std::unique_ptr<RingBuffer<float>>
|
||||||
(m_channelData[c]->inbuf->resized(newSize));
|
(m_channelData[c]->inbuf->resized(newInSize));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_log.log(1, "setMaxProcessSize: nothing to be done, newSize <= oldSize", newSize, oldSize);
|
m_log.log(1, "setMaxProcessSize: nothing to be done at inbuf, newInSize <= oldInSize", newInSize, oldInSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newOutSize > oldOutSize) {
|
||||||
|
m_log.log(1, "setMaxProcessSize: resizing outbuf from and to", oldOutSize, newOutSize);
|
||||||
|
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||||
|
m_channelData[c]->outbuf = std::unique_ptr<RingBuffer<float>>
|
||||||
|
(m_channelData[c]->outbuf->resized(newOutSize));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_log.log(1, "setMaxProcessSize: nothing to be done at outbuf, newOutSize <= oldOutSize", newOutSize, oldOutSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,17 +725,6 @@ R3Stretcher::process(const float *const *input, size_t samples, bool final)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (final) {
|
|
||||||
// We don't distinguish between Finished and "draining, but
|
|
||||||
// haven't yet delivered all the samples" because the
|
|
||||||
// distinction is meaningless internally - it only affects
|
|
||||||
// whether available() finds any samples in the buffer
|
|
||||||
m_log.log(1, "final is set, entering Finished mode");
|
|
||||||
m_mode = ProcessMode::Finished;
|
|
||||||
} else {
|
|
||||||
m_mode = ProcessMode::Processing;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool resamplingBefore = false;
|
bool resamplingBefore = false;
|
||||||
areWeResampling(&resamplingBefore, nullptr);
|
areWeResampling(&resamplingBefore, nullptr);
|
||||||
|
|
||||||
@@ -730,7 +735,7 @@ R3Stretcher::process(const float *const *input, size_t samples, bool final)
|
|||||||
|
|
||||||
m_log.log(2, "process: no samples but final specified, consuming");
|
m_log.log(2, "process: no samples but final specified, consuming");
|
||||||
|
|
||||||
consume();
|
consume(true);
|
||||||
|
|
||||||
} else while (inputIx < int(samples)) {
|
} else while (inputIx < int(samples)) {
|
||||||
|
|
||||||
@@ -738,7 +743,7 @@ R3Stretcher::process(const float *const *input, size_t samples, bool final)
|
|||||||
int ws = m_channelData[0]->inbuf->getWriteSpace();
|
int ws = m_channelData[0]->inbuf->getWriteSpace();
|
||||||
|
|
||||||
if (ws == 0) {
|
if (ws == 0) {
|
||||||
consume();
|
consume(false);
|
||||||
ws = m_channelData[0]->inbuf->getWriteSpace();
|
ws = m_channelData[0]->inbuf->getWriteSpace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -772,13 +777,16 @@ R3Stretcher::process(const float *const *input, size_t samples, bool final)
|
|||||||
|
|
||||||
prepareInput(input, inputIx, resampleInput);
|
prepareInput(input, inputIx, resampleInput);
|
||||||
|
|
||||||
|
bool finalHop = (final &&
|
||||||
|
inputIx + resampleInput >= int(samples));
|
||||||
|
|
||||||
int resampleOutput = m_resampler->resample
|
int resampleOutput = m_resampler->resample
|
||||||
(m_channelAssembly.resampled.data(),
|
(m_channelAssembly.resampled.data(),
|
||||||
maxResampleOutput,
|
maxResampleOutput,
|
||||||
m_channelAssembly.input.data(),
|
m_channelAssembly.input.data(),
|
||||||
resampleInput,
|
resampleInput,
|
||||||
1.0 / m_pitchScale,
|
1.0 / m_pitchScale,
|
||||||
final);
|
finalHop);
|
||||||
|
|
||||||
inputIx += resampleInput;
|
inputIx += resampleInput;
|
||||||
|
|
||||||
@@ -804,7 +812,18 @@ R3Stretcher::process(const float *const *input, size_t samples, bool final)
|
|||||||
inputIx += toWrite;
|
inputIx += toWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
consume();
|
consume(final && inputIx >= int(samples));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (final) {
|
||||||
|
// We don't distinguish between Finished and "draining, but
|
||||||
|
// haven't yet delivered all the samples" because the
|
||||||
|
// distinction is meaningless internally - it only affects
|
||||||
|
// whether available() finds any samples in the buffer
|
||||||
|
m_log.log(1, "final is set, entering Finished mode");
|
||||||
|
m_mode = ProcessMode::Finished;
|
||||||
|
} else {
|
||||||
|
m_mode = ProcessMode::Processing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,6 +845,8 @@ R3Stretcher::retrieve(float *const *output, size_t samples) const
|
|||||||
|
|
||||||
int got = samples;
|
int got = samples;
|
||||||
|
|
||||||
|
m_log.log(2, "retrieve: requested, outbuf has", samples, m_channelData[0]->outbuf->getReadSpace());
|
||||||
|
|
||||||
for (int c = 0; c < m_parameters.channels; ++c) {
|
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||||
int gotHere = m_channelData[c]->outbuf->read(output[c], got);
|
int gotHere = m_channelData[c]->outbuf->read(output[c], got);
|
||||||
if (gotHere < got) {
|
if (gotHere < got) {
|
||||||
@@ -847,6 +868,8 @@ R3Stretcher::retrieve(float *const *output, size_t samples) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_log.log(2, "retrieve: returning, outbuf now has", got, m_channelData[0]->outbuf->getReadSpace());
|
||||||
|
|
||||||
return got;
|
return got;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -874,7 +897,7 @@ R3Stretcher::prepareInput(const float *const *input, int ix, int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
R3Stretcher::consume()
|
R3Stretcher::consume(bool final)
|
||||||
{
|
{
|
||||||
Profiler profiler("R3Stretcher::consume");
|
Profiler profiler("R3Stretcher::consume");
|
||||||
|
|
||||||
@@ -927,23 +950,23 @@ R3Stretcher::consume()
|
|||||||
auto &cd0 = m_channelData.at(0);
|
auto &cd0 = m_channelData.at(0);
|
||||||
|
|
||||||
m_log.log(2, "consume: write space and outhop", cd0->outbuf->getWriteSpace(), outhop);
|
m_log.log(2, "consume: write space and outhop", cd0->outbuf->getWriteSpace(), outhop);
|
||||||
|
|
||||||
while (cd0->outbuf->getWriteSpace() >= outhop) {
|
// NB our ChannelData, ScaleData, and ChannelScaleData maps
|
||||||
|
// contain shared_ptrs; whenever we retain one of them in a
|
||||||
|
// variable, we do so by reference to avoid copying the shared_ptr
|
||||||
|
// (as that is not realtime safe). Same goes for the map iterators
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
Profiler profiler("R3Stretcher::consume/loop");
|
Profiler profiler("R3Stretcher::consume/loop");
|
||||||
|
|
||||||
// NB our ChannelData, ScaleData, and ChannelScaleData maps
|
|
||||||
// contain shared_ptrs; whenever we retain one of them in a
|
|
||||||
// variable, we do so by reference to avoid copying the
|
|
||||||
// shared_ptr (as that is not realtime safe). Same goes for
|
|
||||||
// the map iterators
|
|
||||||
|
|
||||||
int readSpace = cd0->inbuf->getReadSpace();
|
int readSpace = cd0->inbuf->getReadSpace();
|
||||||
|
int writeSpace = cd0->outbuf->getWriteSpace();
|
||||||
|
|
||||||
m_log.log(2, "consume: read space and window source size", readSpace, getWindowSourceSize());
|
m_log.log(2, "consume: read space and write space", readSpace, writeSpace);
|
||||||
|
|
||||||
if (readSpace < getWindowSourceSize()) {
|
if (readSpace < getWindowSourceSize()) {
|
||||||
if (m_mode == ProcessMode::Finished) {
|
if (final) {
|
||||||
if (readSpace == 0) {
|
if (readSpace == 0) {
|
||||||
int fill = cd0->scales.at(longest)->accumulatorFill;
|
int fill = cd0->scales.at(longest)->accumulatorFill;
|
||||||
if (fill == 0) {
|
if (fill == 0) {
|
||||||
@@ -957,7 +980,20 @@ R3Stretcher::consume()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (writeSpace < outhop) {
|
||||||
|
m_log.log(0, "R3Stretcher::process: WARNING: Forced to increase output buffer size. Using smaller process blocks or an artificially larger value for setMaxProcessSize may avoid this");
|
||||||
|
size_t oldSize = m_channelData[0]->outbuf->getSize();
|
||||||
|
size_t newSize = oldSize * 2;
|
||||||
|
m_log.log(0, "R3Stretcher::process: old and new sizes", oldSize, newSize);
|
||||||
|
for (int c = 0; c < m_parameters.channels; ++c) {
|
||||||
|
auto newBuf = m_channelData[c]->outbuf->resized(newSize);
|
||||||
|
m_channelData[c]->outbuf =
|
||||||
|
std::unique_ptr<RingBuffer<float>>(newBuf);
|
||||||
|
}
|
||||||
|
writeSpace = m_channelData[0]->outbuf->getWriteSpace();
|
||||||
|
}
|
||||||
|
|
||||||
// Analysis
|
// Analysis
|
||||||
|
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
@@ -1009,9 +1045,9 @@ R3Stretcher::consume()
|
|||||||
m_channelAssembly.resampled[c] = cd->resampled.data();
|
m_channelAssembly.resampled[c] = cd->resampled.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool final = (m_mode == ProcessMode::Finished &&
|
bool finalHop = (final &&
|
||||||
readSpace < inhop &&
|
readSpace < inhop &&
|
||||||
cd0->scales.at(longest)->accumulatorFill <= outhop);
|
cd0->scales.at(longest)->accumulatorFill <= outhop);
|
||||||
|
|
||||||
resampledCount = m_resampler->resample
|
resampledCount = m_resampler->resample
|
||||||
(m_channelAssembly.resampled.data(),
|
(m_channelAssembly.resampled.data(),
|
||||||
@@ -1019,7 +1055,7 @@ R3Stretcher::consume()
|
|||||||
m_channelAssembly.mixdown.data(),
|
m_channelAssembly.mixdown.data(),
|
||||||
outhop,
|
outhop,
|
||||||
1.0 / m_pitchScale,
|
1.0 / m_pitchScale,
|
||||||
final);
|
finalHop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit
|
// Emit
|
||||||
@@ -1041,8 +1077,8 @@ R3Stretcher::consume()
|
|||||||
|
|
||||||
int advanceCount = inhop;
|
int advanceCount = inhop;
|
||||||
if (advanceCount > readSpace) {
|
if (advanceCount > readSpace) {
|
||||||
// This should happen only when draining (Finished)
|
// This should happen only when draining
|
||||||
if (m_mode != ProcessMode::Finished) {
|
if (!final) {
|
||||||
m_log.log(0, "R3Stretcher: WARNING: readSpace < inhop when processing is not yet finished", readSpace, inhop);
|
m_log.log(0, "R3Stretcher: WARNING: readSpace < inhop when processing is not yet finished", readSpace, inhop);
|
||||||
}
|
}
|
||||||
advanceCount = readSpace;
|
advanceCount = readSpace;
|
||||||
@@ -1074,6 +1110,8 @@ R3Stretcher::consume()
|
|||||||
m_prevInhop = inhop;
|
m_prevInhop = inhop;
|
||||||
m_prevOuthop = outhop;
|
m_prevOuthop = outhop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_log.log(2, "consume: write space reduced to", cd0->outbuf->getWriteSpace());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -228,10 +228,10 @@ protected:
|
|||||||
std::unique_ptr<FormantData> formant;
|
std::unique_ptr<FormantData> formant;
|
||||||
ChannelData(BinSegmenter::Parameters segmenterParameters,
|
ChannelData(BinSegmenter::Parameters segmenterParameters,
|
||||||
BinClassifier::Parameters classifierParameters,
|
BinClassifier::Parameters classifierParameters,
|
||||||
int /*!!! longestFftSize */,
|
|
||||||
int windowSourceSize,
|
int windowSourceSize,
|
||||||
int inRingBufferSize,
|
int inRingBufferSize,
|
||||||
int outRingBufferSize) :
|
int outRingBufferSize,
|
||||||
|
int hopBufferSize) :
|
||||||
scales(),
|
scales(),
|
||||||
windowSource(windowSourceSize, 0.0),
|
windowSource(windowSourceSize, 0.0),
|
||||||
readahead(segmenterParameters.fftSize),
|
readahead(segmenterParameters.fftSize),
|
||||||
@@ -243,8 +243,8 @@ protected:
|
|||||||
BinClassifier::Classification::Residual),
|
BinClassifier::Classification::Residual),
|
||||||
segmenter(new BinSegmenter(segmenterParameters)),
|
segmenter(new BinSegmenter(segmenterParameters)),
|
||||||
segmentation(), prevSegmentation(), nextSegmentation(),
|
segmentation(), prevSegmentation(), nextSegmentation(),
|
||||||
mixdown(inRingBufferSize, 0.f),
|
mixdown(hopBufferSize, 0.f),
|
||||||
resampled(outRingBufferSize, 0.f),
|
resampled(hopBufferSize, 0.f),
|
||||||
inbuf(new RingBuffer<float>(inRingBufferSize)),
|
inbuf(new RingBuffer<float>(inRingBufferSize)),
|
||||||
outbuf(new RingBuffer<float>(outRingBufferSize)),
|
outbuf(new RingBuffer<float>(outRingBufferSize)),
|
||||||
formant(new FormantData(segmenterParameters.fftSize)) { }
|
formant(new FormantData(segmenterParameters.fftSize)) { }
|
||||||
@@ -359,7 +359,7 @@ protected:
|
|||||||
|
|
||||||
void initialise();
|
void initialise();
|
||||||
void prepareInput(const float *const *input, int ix, int n);
|
void prepareInput(const float *const *input, int ix, int n);
|
||||||
void consume();
|
void consume(bool final);
|
||||||
void createResampler();
|
void createResampler();
|
||||||
void calculateHop();
|
void calculateHop();
|
||||||
void updateRatioFromMap();
|
void updateRatioFromMap();
|
||||||
|
|||||||
Reference in New Issue
Block a user