Provide a separate window source buffer to simplify single/multi window logic

This commit is contained in:
Chris Cannam
2022-08-04 10:02:09 +01:00
parent 2fa0e1162e
commit d1386b0a0c
2 changed files with 27 additions and 25 deletions

View File

@@ -44,6 +44,7 @@ R3Stretcher::R3Stretcher(Parameters parameters,
m_parameters.options & RubberBandStretcher::OptionWindowShort), m_parameters.options & RubberBandStretcher::OptionWindowShort),
m_log), m_log),
m_guideConfiguration(m_guide.getConfiguration()), m_guideConfiguration(m_guide.getConfiguration()),
m_windowSourceBuffer(getWindowSourceBufferLength()),
m_channelAssembly(m_parameters.channels), m_channelAssembly(m_parameters.channels),
m_inhop(1), m_inhop(1),
m_prevInhop(1), m_prevInhop(1),
@@ -75,14 +76,6 @@ R3Stretcher::R3Stretcher(Parameters parameters,
m_log.log(1, "R3Stretcher::R3Stretcher: intermediate shorter-window mode requested"); m_log.log(1, "R3Stretcher::R3Stretcher: intermediate shorter-window mode requested");
} }
if (m_guideConfiguration.longestFftSize >
m_guideConfiguration.classificationFftSize) {
m_timeDomainFrameLength = m_guideConfiguration.longestFftSize;
} else {
m_timeDomainFrameLength =
(m_guideConfiguration.classificationFftSize * 3) / 2;
}
double maxClassifierFrequency = 16000.0; double maxClassifierFrequency = 16000.0;
if (maxClassifierFrequency > m_parameters.sampleRate/2) { if (maxClassifierFrequency > m_parameters.sampleRate/2) {
maxClassifierFrequency = m_parameters.sampleRate/2; maxClassifierFrequency = m_parameters.sampleRate/2;
@@ -98,14 +91,14 @@ R3Stretcher::R3Stretcher(Parameters parameters,
BinClassifier::Parameters classifierParameters BinClassifier::Parameters classifierParameters
(classificationBins, 9, 1, 10, 2.0, 2.0); (classificationBins, 9, 1, 10, 2.0, 2.0);
int inRingBufferSize = m_timeDomainFrameLength * 2; int inRingBufferSize = getWindowSourceBufferLength() * 2;
int outRingBufferSize = m_timeDomainFrameLength * 16; int outRingBufferSize = getWindowSourceBufferLength() * 16;
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_timeDomainFrameLength, m_guideConfiguration.longestFftSize,
inRingBufferSize, inRingBufferSize,
outRingBufferSize)); outRingBufferSize));
for (int b = 0; b < m_guideConfiguration.fftBandLimitCount; ++b) { for (int b = 0; b < m_guideConfiguration.fftBandLimitCount; ++b) {
@@ -113,7 +106,7 @@ R3Stretcher::R3Stretcher(Parameters parameters,
int fftSize = band.fftSize; int fftSize = band.fftSize;
m_channelData[c]->scales[fftSize] = m_channelData[c]->scales[fftSize] =
std::make_shared<ChannelScaleData> std::make_shared<ChannelScaleData>
(fftSize, m_timeDomainFrameLength); (fftSize, m_guideConfiguration.longestFftSize);
} }
} }
@@ -283,7 +276,7 @@ R3Stretcher::createResampler()
} }
resamplerParameters.initialSampleRate = m_parameters.sampleRate; resamplerParameters.initialSampleRate = m_parameters.sampleRate;
resamplerParameters.maxBufferSize = m_timeDomainFrameLength; resamplerParameters.maxBufferSize = m_guideConfiguration.longestFftSize;
if (isRealTime()) { if (isRealTime()) {
// If we knew the caller would never change ratio, we could // If we knew the caller would never change ratio, we could
@@ -457,7 +450,7 @@ R3Stretcher::getPreferredStartPad() const
if (!isRealTime()) { if (!isRealTime()) {
return 0; return 0;
} else { } else {
return m_timeDomainFrameLength / 2; return m_windowSourceBuffer.size() / 2;
} }
} }
@@ -468,7 +461,7 @@ R3Stretcher::getStartDelay() const
return 0; return 0;
} else { } else {
double factor = 0.5 / m_pitchScale; double factor = 0.5 / m_pitchScale;
return size_t(ceil(m_timeDomainFrameLength * factor)); return size_t(ceil(m_windowSourceBuffer.size() * factor));
} }
} }
@@ -542,8 +535,8 @@ R3Stretcher::getSamplesRequired() const
{ {
if (available() != 0) return 0; if (available() != 0) return 0;
int rs = m_channelData[0]->inbuf->getReadSpace(); int rs = m_channelData[0]->inbuf->getReadSpace();
if (rs < m_timeDomainFrameLength) { if (rs < m_windowSourceBuffer.size()) {
return m_timeDomainFrameLength - rs; return m_windowSourceBuffer.size() - rs;
} else { } else {
return 0; return 0;
} }
@@ -553,7 +546,7 @@ void
R3Stretcher::setMaxProcessSize(size_t n) R3Stretcher::setMaxProcessSize(size_t n)
{ {
size_t oldSize = m_channelData[0]->inbuf->getSize(); size_t oldSize = m_channelData[0]->inbuf->getSize();
size_t newSize = m_timeDomainFrameLength + n; size_t newSize = m_windowSourceBuffer.size() + n;
if (newSize > oldSize) { if (newSize > oldSize) {
m_log.log(1, "setMaxProcessSize: resizing from and to", oldSize, newSize); m_log.log(1, "setMaxProcessSize: resizing from and to", oldSize, newSize);
@@ -612,7 +605,7 @@ R3Stretcher::process(const float *const *input, size_t samples, bool final)
// don't do this -- it's better to start with a swoosh // don't do this -- it's better to start with a swoosh
// than introduce more latency, and we don't want gaps // than introduce more latency, and we don't want gaps
// when the ratio changes. // when the ratio changes.
int pad = m_timeDomainFrameLength / 2; int pad = m_windowSourceBuffer.size() / 2;
m_log.log(1, "offline mode: prefilling with", pad); m_log.log(1, "offline mode: prefilling with", pad);
for (int c = 0; c < m_parameters.channels; ++c) { for (int c = 0; c < m_parameters.channels; ++c) {
m_channelData[c]->inbuf->zero(pad); m_channelData[c]->inbuf->zero(pad);
@@ -744,7 +737,7 @@ R3Stretcher::consume()
// the map iterators // the map iterators
int readSpace = cd0->inbuf->getReadSpace(); int readSpace = cd0->inbuf->getReadSpace();
if (readSpace < m_timeDomainFrameLength) { if (readSpace < m_windowSourceBuffer.size()) {
if (m_mode == ProcessMode::Finished) { if (m_mode == ProcessMode::Finished) {
if (readSpace == 0) { if (readSpace == 0) {
int fill = cd0->scales.at(longest)->accumulatorFill; int fill = cd0->scales.at(longest)->accumulatorFill;

View File

@@ -132,7 +132,7 @@ protected:
FixedVector<process_t> accumulator; FixedVector<process_t> accumulator;
int accumulatorFill; int accumulatorFill;
ChannelScaleData(int _fftSize, int _timeDomainLength) : ChannelScaleData(int _fftSize, int _longestFftSize) :
fftSize(_fftSize), fftSize(_fftSize),
bufSize(fftSize/2 + 1), bufSize(fftSize/2 + 1),
timeDomain(fftSize, 0.f), timeDomain(fftSize, 0.f),
@@ -143,7 +143,7 @@ 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(_timeDomainLength, 0.f), accumulator(_longestFftSize, 0.f),
accumulatorFill(0) accumulatorFill(0)
{ } { }
@@ -202,7 +202,7 @@ 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 timeDomainLength, int longestFftSize,
int inRingBufferSize, int inRingBufferSize,
int outRingBufferSize) : int outRingBufferSize) :
scales(), scales(),
@@ -215,7 +215,7 @@ protected:
BinClassifier::Classification::Residual), BinClassifier::Classification::Residual),
segmenter(new BinSegmenter(segmenterParameters)), segmenter(new BinSegmenter(segmenterParameters)),
segmentation(), prevSegmentation(), nextSegmentation(), segmentation(), prevSegmentation(), nextSegmentation(),
mixdown(timeDomainLength, 0.f), mixdown(longestFftSize, 0.f),
resampled(outRingBufferSize, 0.f), resampled(outRingBufferSize, 0.f),
inbuf(new RingBuffer<float>(inRingBufferSize)), inbuf(new RingBuffer<float>(inRingBufferSize)),
outbuf(new RingBuffer<float>(outRingBufferSize)), outbuf(new RingBuffer<float>(outRingBufferSize)),
@@ -297,7 +297,7 @@ protected:
std::map<int, std::shared_ptr<ScaleData>> m_scaleData; std::map<int, std::shared_ptr<ScaleData>> m_scaleData;
Guide m_guide; Guide m_guide;
Guide::Configuration m_guideConfiguration; Guide::Configuration m_guideConfiguration;
int m_timeDomainFrameLength; FixedVector<process_t> m_windowSourceBuffer;
ChannelAssembly m_channelAssembly; ChannelAssembly m_channelAssembly;
std::unique_ptr<StretchCalculator> m_calculator; std::unique_ptr<StretchCalculator> m_calculator;
std::unique_ptr<Resampler> m_resampler; std::unique_ptr<Resampler> m_resampler;
@@ -376,6 +376,15 @@ protected:
return m_parameters.options & return m_parameters.options &
RubberBandStretcher::OptionWindowShort; RubberBandStretcher::OptionWindowShort;
} }
int getWindowSourceBufferLength() const {
if (m_guideConfiguration.longestFftSize >
m_guideConfiguration.classificationFftSize) {
return m_guideConfiguration.longestFftSize;
} else {
return (m_guideConfiguration.classificationFftSize * 3) / 2;
}
}
}; };
} }