From b3745f45dc25c2137668ecf745a3058d47c211bb Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 4 Oct 2023 08:32:40 -0400 Subject: [PATCH] Avoid frequent allocation of little vectors of pointers in stretch --- .../lib-stretching-sequence/AudioSegment.h | 5 ++--- .../lib-stretching-sequence/ClipSegment.cpp | 5 ++--- libraries/lib-stretching-sequence/ClipSegment.h | 2 +- .../lib-stretching-sequence/SilenceSegment.cpp | 3 +-- .../lib-stretching-sequence/SilenceSegment.h | 2 +- .../StretchingSequence.cpp | 17 +++++++++-------- .../tests/ClipSegmentTest.cpp | 4 ++-- .../tests/MockAudioSegmentFactory.h | 2 +- .../tests/SilenceSegmentTest.cpp | 4 ++-- .../lib-time-and-pitch/StaffPadTimeAndPitch.cpp | 15 ++++++--------- 10 files changed, 27 insertions(+), 32 deletions(-) diff --git a/libraries/lib-stretching-sequence/AudioSegment.h b/libraries/lib-stretching-sequence/AudioSegment.h index 9470641d484c..dfb852cc28d8 100644 --- a/libraries/lib-stretching-sequence/AudioSegment.h +++ b/libraries/lib-stretching-sequence/AudioSegment.h @@ -27,13 +27,12 @@ class STRETCHING_SEQUENCE_API AudioSegment /** * @brief Fills `buffers` with as many as `numSamples` or the number of * remaining samples, whichever is smaller. - * @param buffers A vector of pointers to buffers, one for each channel. + * @param buffers Pointers to buffers, one for each channel. * @param numSamples The max. number of samples to write to each buffer. - * @pre `buffers.size() == GetWidth()` * @return The number of samples actually provided in each buffer. */ virtual size_t - GetFloats(std::vector& buffers, size_t numSamples) = 0; + GetFloats(float *const *buffers, size_t numSamples) = 0; /** * @brief The number of channels in the segment. diff --git a/libraries/lib-stretching-sequence/ClipSegment.cpp b/libraries/lib-stretching-sequence/ClipSegment.cpp index 167b40d0f8db..090c163b462f 100644 --- a/libraries/lib-stretching-sequence/ClipSegment.cpp +++ b/libraries/lib-stretching-sequence/ClipSegment.cpp @@ -46,12 +46,11 @@ ClipSegment::ClipSegment( { } -size_t ClipSegment::GetFloats(std::vector& buffers, size_t numSamples) +size_t ClipSegment::GetFloats(float *const *buffers, size_t numSamples) { - assert(buffers.size() == mSource.GetWidth()); const auto numSamplesToProduce = limitSampleBufferSize( numSamples, mTotalNumSamplesToProduce - mTotalNumSamplesProduced); - mStretcher->GetSamples(buffers.data(), numSamplesToProduce); + mStretcher->GetSamples(buffers, numSamplesToProduce); mTotalNumSamplesProduced += numSamplesToProduce; return numSamplesToProduce; } diff --git a/libraries/lib-stretching-sequence/ClipSegment.h b/libraries/lib-stretching-sequence/ClipSegment.h index 2acce0962b3c..1e1e516f05c3 100644 --- a/libraries/lib-stretching-sequence/ClipSegment.h +++ b/libraries/lib-stretching-sequence/ClipSegment.h @@ -26,7 +26,7 @@ class STRETCHING_SEQUENCE_API ClipSegment final : public AudioSegment const ClipInterface&, double durationToDiscard, PlaybackDirection); // AudioSegment - size_t GetFloats(std::vector& buffers, size_t numSamples) override; + size_t GetFloats(float *const *buffers, size_t numSamples) override; bool Empty() const override; size_t GetWidth() const override; diff --git a/libraries/lib-stretching-sequence/SilenceSegment.cpp b/libraries/lib-stretching-sequence/SilenceSegment.cpp index 9aa0f01b5d5f..7339aa2c98a0 100644 --- a/libraries/lib-stretching-sequence/SilenceSegment.cpp +++ b/libraries/lib-stretching-sequence/SilenceSegment.cpp @@ -20,9 +20,8 @@ SilenceSegment::SilenceSegment(size_t numChannels, sampleCount numSamples) } size_t -SilenceSegment::GetFloats(std::vector& buffers, size_t numSamples) +SilenceSegment::GetFloats(float *const *buffers, size_t numSamples) { - assert(buffers.size() == mNumChannels); const size_t numSamplesToProduce = std::min(mNumRemainingSamples.as_long_long(), numSamples); for (auto i = 0u; i < mNumChannels; ++i) diff --git a/libraries/lib-stretching-sequence/SilenceSegment.h b/libraries/lib-stretching-sequence/SilenceSegment.h index 3e6533425ea9..a12300237cad 100644 --- a/libraries/lib-stretching-sequence/SilenceSegment.h +++ b/libraries/lib-stretching-sequence/SilenceSegment.h @@ -18,7 +18,7 @@ class STRETCHING_SEQUENCE_API SilenceSegment final : public AudioSegment { public: SilenceSegment(size_t numChannels, sampleCount numSamples); - size_t GetFloats(std::vector& buffers, size_t numSamples) override; + size_t GetFloats(float *const *buffers, size_t numSamples) override; bool Empty() const override; size_t GetWidth() const override; diff --git a/libraries/lib-stretching-sequence/StretchingSequence.cpp b/libraries/lib-stretching-sequence/StretchingSequence.cpp index 5496786a958b..5dc658a7101f 100644 --- a/libraries/lib-stretching-sequence/StretchingSequence.cpp +++ b/libraries/lib-stretching-sequence/StretchingSequence.cpp @@ -17,13 +17,12 @@ namespace { -std::vector -GetOffsetBuffer(float* const* buffer, size_t numChannels, size_t offset) +void +GetOffsetBuffer(float **offsetBuffer, + float* const* buffer, size_t numChannels, size_t offset) { - std::vector offsetBuffer(numChannels); for (auto i = 0u; i < numChannels; ++i) offsetBuffer[i] = buffer[i] + offset; - return offsetBuffer; } } // namespace @@ -54,8 +53,9 @@ bool StretchingSequence::GetNext( mActiveAudioSegmentIt != mAudioSegments.end()) { const auto& segment = *mActiveAudioSegmentIt; - auto offsetBuffers = - GetOffsetBuffer(buffers, mSequence.NChannels(), numProcessedSamples); + float *offsetBuffers[2]{}; + GetOffsetBuffer(offsetBuffers, + buffers, mSequence.NChannels(), numProcessedSamples); numProcessedSamples += segment->GetFloats( offsetBuffers, numSamples - numProcessedSamples); // No need to reverse, we feed the @@ -67,8 +67,9 @@ bool StretchingSequence::GetNext( const auto remaining = numSamples - numProcessedSamples; if (remaining > 0u) { - const auto offsetBuffers = - GetOffsetBuffer(buffers, mSequence.NChannels(), numProcessedSamples); + float *offsetBuffers[2]{}; + GetOffsetBuffer( + offsetBuffers, buffers, mSequence.NChannels(), numProcessedSamples); for (auto i = 0u; i < mSequence.NChannels(); ++i) std::fill(offsetBuffers[i], offsetBuffers[i] + remaining, 0.f); } diff --git a/libraries/lib-stretching-sequence/tests/ClipSegmentTest.cpp b/libraries/lib-stretching-sequence/tests/ClipSegmentTest.cpp index 15d63d2d50c4..6fefda1996b7 100644 --- a/libraries/lib-stretching-sequence/tests/ClipSegmentTest.cpp +++ b/libraries/lib-stretching-sequence/tests/ClipSegmentTest.cpp @@ -38,7 +38,7 @@ TEST_CASE("ClipSegment") FloatVectorVector { { 1.f, 2.f, 3.f }, { -1.f, -2.f, -3.f } }); ClipSegment sut { *clip, 0., direction }; AudioContainer output(sampleRate, numChannels); - REQUIRE(sut.GetFloats(output.channelPointers, sampleRate) == sampleRate); + REQUIRE(sut.GetFloats(output.channelPointers.data(), sampleRate) == sampleRate); if (numChannels == 1u) { const auto expected = direction == PlaybackDirection::forward ? @@ -69,7 +69,7 @@ TEST_CASE("ClipSegment") constexpr auto playbackOffset = 2 / static_cast(sampleRate); ClipSegment sut { *clip, playbackOffset, direction }; AudioContainer output(numSamples, 1u); - REQUIRE(sut.GetFloats(output.channelPointers, numSamples) == 3); + REQUIRE(sut.GetFloats(output.channelPointers.data(), numSamples) == 3); const auto expected = direction == PlaybackDirection::forward ? std::vector { 3.f, 4.f, 5.f, 0.f, 0.f } : std::vector { 3.f, 2.f, 1.f, 0.f, 0.f }; diff --git a/libraries/lib-stretching-sequence/tests/MockAudioSegmentFactory.h b/libraries/lib-stretching-sequence/tests/MockAudioSegmentFactory.h index b76ef56a1023..50a1ff122ddc 100644 --- a/libraries/lib-stretching-sequence/tests/MockAudioSegmentFactory.h +++ b/libraries/lib-stretching-sequence/tests/MockAudioSegmentFactory.h @@ -16,7 +16,7 @@ class NiceAudioSegment final : public AudioSegment { public: - size_t GetFloats(std::vector&, size_t numSamples) override + size_t GetFloats(float *const *, size_t numSamples) override { return numSamples; } diff --git a/libraries/lib-stretching-sequence/tests/SilenceSegmentTest.cpp b/libraries/lib-stretching-sequence/tests/SilenceSegmentTest.cpp index 5a13b29f7c39..a0b981d559eb 100644 --- a/libraries/lib-stretching-sequence/tests/SilenceSegmentTest.cpp +++ b/libraries/lib-stretching-sequence/tests/SilenceSegmentTest.cpp @@ -21,8 +21,8 @@ TEST_CASE("SilenceSegment", "behaves as expected") SilenceSegment sut(numChannels, silenceSegmentLength); REQUIRE(!sut.Empty()); AudioContainer container(3u, numChannels); - REQUIRE(sut.GetFloats(container.channelPointers, 1) == 1); + REQUIRE(sut.GetFloats(container.channelPointers.data(), 1) == 1); REQUIRE(!sut.Empty()); - REQUIRE(sut.GetFloats(container.channelPointers, 3) == 2); + REQUIRE(sut.GetFloats(container.channelPointers.data(), 3) == 2); REQUIRE(sut.Empty()); } diff --git a/libraries/lib-time-and-pitch/StaffPadTimeAndPitch.cpp b/libraries/lib-time-and-pitch/StaffPadTimeAndPitch.cpp index 6ee28edc4861..3f6d4e5d8c80 100644 --- a/libraries/lib-time-and-pitch/StaffPadTimeAndPitch.cpp +++ b/libraries/lib-time-and-pitch/StaffPadTimeAndPitch.cpp @@ -10,15 +10,12 @@ namespace // to be specified in the `setup` call.) constexpr auto maxBlockSize = 1024; -std::vector -GetOffsetBuffer(float* const* buffer, size_t numChannels, size_t offset) +void +GetOffsetBuffer(float **offsetBuffer, + float* const* buffer, size_t numChannels, size_t offset) { - std::vector offsetBuffer(numChannels); for (auto i = 0u; i < numChannels; ++i) - { offsetBuffer[i] = buffer[i] + offset; - } - return offsetBuffer; } std::unique_ptr MaybeCreateTimeAndPitch( @@ -82,9 +79,9 @@ void StaffPadTimeAndPitch::GetSamples(float* const* output, size_t outputLen) const auto numSamplesToGet = std::min({ maxBlockSize, numOutputSamplesAvailable, static_cast(outputLen - numOutputSamples) }); - const auto buffer = - GetOffsetBuffer(output, mNumChannels, numOutputSamples); - mTimeAndPitch->retrieveAudio(buffer.data(), numSamplesToGet); + float *buffer[2]{}; + GetOffsetBuffer(buffer, output, mNumChannels, numOutputSamples); + mTimeAndPitch->retrieveAudio(buffer, numSamplesToGet); numOutputSamplesAvailable -= numSamplesToGet; numOutputSamples += numSamplesToGet; }