diff --git a/src/faster/R2Stretcher.cpp b/src/faster/R2Stretcher.cpp index 4159c24..52737a4 100644 --- a/src/faster/R2Stretcher.cpp +++ b/src/faster/R2Stretcher.cpp @@ -993,6 +993,8 @@ R2Stretcher::study(const float *const *input, size_t samples, bool final) mixdown = input[0]; } + std::vector optionalFoldBuffer; + while (consumed < samples) { size_t writable = inbuf.getWriteSpace(); @@ -1042,15 +1044,18 @@ R2Stretcher::study(const float *const *input, size_t samples, bool final) // Note that we can't do this in-place. Pity - float *tmp = (float *)alloca - (std::max(m_fftSize, m_aWindowSize) * sizeof(float)); + // This doesn't have to be allocation-free, as we're + // in offline-mode study + + optionalFoldBuffer.resize(std::max(m_fftSize, m_aWindowSize)); if (m_aWindowSize > m_fftSize) { m_afilter->cut(cd.accumulator); } - cutShiftAndFold(tmp, m_fftSize, cd.accumulator, m_awindow); - v_copy(cd.accumulator, tmp, m_fftSize); + cutShiftAndFold(optionalFoldBuffer.data(), m_fftSize, + cd.accumulator, m_awindow); + v_copy(cd.accumulator, optionalFoldBuffer.data(), m_fftSize); } m_studyFFT->forwardMagnitude(cd.accumulator, cd.fltbuf); @@ -1058,8 +1063,6 @@ R2Stretcher::study(const float *const *input, size_t samples, bool final) float df = m_phaseResetAudioCurve->processFloat(cd.fltbuf, m_increment); m_phaseResetDf.push_back(df); -// cout << m_phaseResetDf.size() << " [" << final << "] -> " << df << " \t: "; - df = m_silentAudioCurve->processFloat(cd.fltbuf, m_increment); bool silent = (df > 0.f); if (silent) { @@ -1067,8 +1070,6 @@ R2Stretcher::study(const float *const *input, size_t samples, bool final) } m_silence.push_back(silent); -// cout << df << endl; - // We have augmented the input by m_aWindowSize/2 so that // the first chunk is centred on the first audio sample. // We want to ensure that m_inputDuration contains the @@ -1080,7 +1081,7 @@ R2Stretcher::study(const float *const *input, size_t samples, bool final) inbuf.skip(m_increment); } } - + if (final) { int rs = inbuf.getReadSpace(); m_inputDuration += rs; diff --git a/src/faster/StretcherProcess.cpp b/src/faster/StretcherProcess.cpp index 36fe27b..74d09e7 100644 --- a/src/faster/StretcherProcess.cpp +++ b/src/faster/StretcherProcess.cpp @@ -236,6 +236,9 @@ R2Stretcher::consumeChannel(size_t c, inbuf.write(cd.resamplebuf, toWrite); cd.inCount += samples; + + m_log.log(2, "consumeChannel: wrote to inbuf from resamplebuf, inCount now", toWrite, cd.inCount); + return samples; } else { @@ -249,6 +252,9 @@ R2Stretcher::consumeChannel(size_t c, inbuf.write(input, toWrite); cd.inCount += toWrite; + + m_log.log(2, "consumeChannel: wrote to inbuf from input, inCount now", toWrite, cd.inCount); + return toWrite; } } @@ -340,7 +346,7 @@ R2Stretcher::processOneChunk() return false; } ChannelData &cd = *m_channelData[c]; - m_log.log(3, "read space and draining", cd.inbuf->getReadSpace(), cd.draining); + m_log.log(2, "read space and draining", cd.inbuf->getReadSpace(), cd.draining); if (!cd.draining) { size_t ready = cd.inbuf->getReadSpace(); assert(ready >= m_aWindowSize || cd.inputSize >= 0); diff --git a/src/test/TestStretcher.cpp b/src/test/TestStretcher.cpp index fc72d99..a2352c4 100644 --- a/src/test/TestStretcher.cpp +++ b/src/test/TestStretcher.cpp @@ -1516,4 +1516,32 @@ BOOST_AUTO_TEST_CASE(with_resets_2x_5up_realtime_faster) with_resets(RubberBandStretcher::OptionProcessRealTime | RubberBandStretcher::OptionEngineFaster, 2.0, 1.5); } +BOOST_AUTO_TEST_CASE(long_blocksize_with_smoothing) +{ + // Test added because the smoothing option was calling alloca in a + // loop, which could run us out of stack. This test is best used + // with a small stack artificially enforced via e.g. ulimit -s 32 + + int n = 10000; + float freq = 440.f; + int rate = 44100; + RubberBandStretcher stretcher + (rate, 1, + RubberBandStretcher::OptionEngineFaster | + RubberBandStretcher::OptionProcessOffline | + RubberBandStretcher::OptionSmoothingOn); + + vector in(n); + for (int i = 0; i < n; ++i) { + in[i] = sinf(float(i) * freq * M_PI * 2.f / float(rate)); + } + float *inp = in.data(); + + stretcher.setMaxProcessSize(n); + stretcher.setExpectedInputDuration(n); + + stretcher.study(&inp, n, true); + stretcher.process(&inp, n, true); +} + BOOST_AUTO_TEST_SUITE_END()