Audacity 3.2.0
StaffPadTimeAndPitch.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cassert>
5#include <memory>
6
7namespace
8{
9// Let's use StaffPad's default value. (We have to reproduce it here as it has
10// to be specified in the `setup` call.)
11constexpr auto maxBlockSize = 1024;
12
13std::vector<float*>
14GetOffsetBuffer(float* const* buffer, size_t numChannels, size_t offset)
15{
16 std::vector<float*> offsetBuffer(numChannels);
17 for (auto i = 0u; i < numChannels; ++i)
18 {
19 offsetBuffer[i] = buffer[i] + offset;
20 }
21 return offsetBuffer;
22}
23
24std::unique_ptr<staffpad::TimeAndPitch> MaybeCreateTimeAndPitch(
25 size_t numChannels, const TimeAndPitchInterface::Parameters& params)
26{
27 const auto timeRatio = params.timeRatio.value_or(1.);
28 const auto pitchRatio = params.pitchRatio.value_or(1.);
29 if (
32 {
33 return nullptr;
34 }
35 auto timeAndPitch = std::make_unique<staffpad::TimeAndPitch>();
36 timeAndPitch->setup(static_cast<int>(numChannels), maxBlockSize);
37 timeAndPitch->setTimeStretchAndPitchFactor(timeRatio, pitchRatio);
38 return timeAndPitch;
39}
40} // namespace
41
43 size_t numChannels, TimeAndPitchSource& audioSource,
44 const Parameters& parameters)
45 : mAudioSource(audioSource)
46 , mReadBuffer(maxBlockSize, numChannels)
47 , mNumChannels(numChannels)
48 , mTimeRatio(parameters.timeRatio.value_or(1.))
49 , mTimeAndPitch(MaybeCreateTimeAndPitch(numChannels, parameters))
50{
52}
53
54void StaffPadTimeAndPitch::GetSamples(float* const* output, size_t outputLen)
55{
56 if (!mTimeAndPitch)
57 // Pass-through
58 return mAudioSource.Pull(output, outputLen);
59
60 auto numOutputSamples = 0u;
61 while (numOutputSamples < outputLen)
62 {
63 auto numOutputSamplesAvailable =
64 mTimeAndPitch->getNumAvailableOutputSamples();
65 while (numOutputSamplesAvailable == 0)
66 {
67 auto numRequired = mTimeAndPitch->getSamplesToNextHop();
68 while (numRequired > 0)
69 {
70 const auto numSamplesToFeed = std::min(numRequired, maxBlockSize);
71 mAudioSource.Pull(mReadBuffer.Get(), numSamplesToFeed);
72 mTimeAndPitch->feedAudio(mReadBuffer.Get(), numSamplesToFeed);
73 numRequired -= numSamplesToFeed;
74 }
75 numOutputSamplesAvailable =
76 mTimeAndPitch->getNumAvailableOutputSamples();
77 }
78 while (numOutputSamples < outputLen && numOutputSamplesAvailable > 0)
79 {
80 const auto numSamplesToGet =
81 std::min({ maxBlockSize, numOutputSamplesAvailable,
82 static_cast<int>(outputLen - numOutputSamples) });
83 const auto buffer =
84 GetOffsetBuffer(output, mNumChannels, numOutputSamples);
85 mTimeAndPitch->retrieveAudio(buffer.data(), numSamplesToGet);
86 numOutputSamplesAvailable -= numSamplesToGet;
87 numOutputSamples += numSamplesToGet;
88 }
89 }
90}
91
93{
94 if (!mTimeAndPitch)
95 {
96 // Bypass
97 return;
98 }
99 auto numOutputSamplesToDiscard =
100 mTimeAndPitch->getLatencySamplesForStretchRatio(mTimeRatio);
102 while (numOutputSamplesToDiscard > 0)
103 {
104 auto numRequired = mTimeAndPitch->getSamplesToNextHop();
105 while (numRequired > 0)
106 {
107 const auto numSamplesToFeed = std::min(maxBlockSize, numRequired);
108 mAudioSource.Pull(container.Get(), numSamplesToFeed);
109 mTimeAndPitch->feedAudio(container.Get(), numSamplesToFeed);
110 numRequired -= numSamplesToFeed;
111 }
112 const auto totalNumSamplesToRetrieve = std::min(
113 mTimeAndPitch->getNumAvailableOutputSamples(),
114 numOutputSamplesToDiscard);
115 auto totalNumRetrievedSamples = 0;
116 while (totalNumRetrievedSamples < totalNumSamplesToRetrieve)
117 {
118 const auto numSamplesToRetrieve = std::min(
119 maxBlockSize, totalNumSamplesToRetrieve - totalNumRetrievedSamples);
120 mTimeAndPitch->retrieveAudio(container.Get(), numSamplesToRetrieve);
121 totalNumRetrievedSamples += numSamplesToRetrieve;
122 }
123 numOutputSamplesToDiscard -= totalNumSamplesToRetrieve;
124 }
125}
int min(int a, int b)
EffectDistortionSettings params
Definition: Distortion.cpp:77
StaffPadTimeAndPitch(size_t numChannels, TimeAndPitchSource &, const Parameters &)
TimeAndPitchSource & mAudioSource
const std::unique_ptr< staffpad::TimeAndPitch > mTimeAndPitch
void GetSamples(float *const *, size_t) override
static bool IsPassThroughMode(double stretchRatio)
virtual void Pull(float *const *, size_t samplesPerChannel)=0
std::unique_ptr< staffpad::TimeAndPitch > MaybeCreateTimeAndPitch(size_t numChannels, const TimeAndPitchInterface::Parameters &params)
std::vector< float * > GetOffsetBuffer(float *const *buffer, size_t numChannels, size_t offset)
float *const * Get() const